.gitignore0100644 0000000 0000000 00000000425 13756670063 011613 0ustar000000000 0000000 # Note: use "git ls-files -i --exclude-standard" to make sure # no tracked files are ignored as a result of any changes. # Object files *.o *.lo *.so *.so.[0-9] *.a *.s *.mo *.pc # Misc *.patch *.gz *~ *.orig *.rej *.pyc *.pyo cscope.* .#* \#* .*.swp # Failsafes !.gitignore .travis.yml0100644 0000000 0000000 00000014217 13756670063 011740 0ustar000000000 0000000 # Define the building environment language: c matrix: fast_finish: true compiler: - clang - gcc env: matrix: # Test the last version of Python and Ruby together, with some linkers - PYVER=python3.7 RUBYLIBVER=2.6 - PYVER=python3.7 RUBYLIBVER=2.6 TEST_FLAGS_OVERRIDE=1 - PYVER=python3.7 RUBYLIBVER=2.6 LINKER=gold - PYVER=python3.7 RUBYLIBVER=2.6 LINKER=bfd # Test several Python versions - PYVER=python2.7 RUBYLIBVER=2.6 - PYVER=python3.5 RUBYLIBVER=2.6 - PYVER=python3.6 RUBYLIBVER=2.6 - PYVER=pypy2.7-6.0 RUBYLIBVER=2.6 - PYVER=pypy3.5-6.0 RUBYLIBVER=2.6 # Test several Ruby versions (http://rubies.travis-ci.org/) - PYVER=python3.7 RUBYLIBVER=2.5.1 - PYVER=python3.7 RUBYLIBVER=2.4 - PYVER=python3.7 RUBYLIBVER=2.3 - PYVER=python3.7 RUBYLIBVER=2.2 matrix: exclude: - compiler: clang env: PYVER=python3.7 RUBYLIBVER=2.6 LINKER=gold - compiler: clang env: PYVER=python3.7 RUBYLIBVER=2.6 LINKER=bfd # Use Travis-CI Ubuntu 16.04 Xenial Xerus infrastructure, "full image" variant sudo: required dist: xenial # Install SELinux userspace utilities dependencies addons: apt: packages: - bison - flex - gawk - gettext - libaudit-dev - libbz2-dev - libcap-dev - libcap-ng-dev # This package is not whitelisted for the container infrastructure (https://github.com/travis-ci/apt-package-whitelist/issues/1096) - libcunit1-dev - libdbus-glib-1-dev - libncurses5-dev - libpcre3-dev - patch - python3-dev - python-dev - swig - xmlto install: # Download and install refpolicy headers for sepolgen tests - curl --location --retry 10 -o "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_2_20180701/refpolicy-2.20180701.tar.bz2 - tar -C "$TRAVIS_BUILD_DIR" -xvjf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" # Make refpolicy Makefile use the new toolchain when building modules - sed -e "s,^PREFIX :=.*,PREFIX := \$(DESTDIR)/usr," -i "$TRAVIS_BUILD_DIR/refpolicy/support/Makefile.devel" - sudo make -C "$TRAVIS_BUILD_DIR/refpolicy" install-headers - sudo rm -rf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" "$TRAVIS_BUILD_DIR/refpolicy" - sudo mkdir -p /etc/selinux - echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config - echo 'SELINUX_DEVEL_PATH = /usr/share/selinux/refpolicy' | sudo tee /etc/selinux/sepolgen.conf # Make sepolgen tests work without really installing anything in the real root (doing this would conflict with Ubuntu packages) - sed -e "s,\"\(/usr/bin/[cs]\),\"$TRAVIS_BUILD_DIR/installdir\1," -i python/sepolgen/src/sepolgen/module.py # Download the required python version if it is not installed - VIRTUAL_ENV="$HOME/virtualenv/$PYVER" - if ! [ -d "$VIRTUAL_ENV" ] ; then curl --retry 10 -o python.tar.bz2 "https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/16.04/x86_64/${PYVER/python/python-}.tar.bz2" && sudo tar xjf python.tar.bz2 --directory / && rm python.tar.bz2 ; fi # Install flake8 for the given python version - $VIRTUAL_ENV/bin/pip install flake8 before_script: # Build and install in a temporary directory to run tests - export DESTDIR="$TRAVIS_BUILD_DIR/installdir" # Configure the variables for Python parts - export VIRTUAL_ENV="$HOME/virtualenv/$PYVER" - export PYTHON="$VIRTUAL_ENV/bin/python" # Use the header files in /opt/python/... for Python because the virtualenvs do not provide Python.h - export PKG_CONFIG_PATH="/opt/python/$($PYTHON -c 'import sys;print("%d.%d.%d" % sys.version_info[:3])')/lib/pkgconfig" # PyPy does not provide a config file for pkg-config # libpypy-c.so is provided in bin/libpypy-c.so for PyPy and bin/libpypy3-c.so for PyPy3 - if echo "$PYVER" | grep -q pypy ; then export PYINC=-I$($PYTHON -c 'import sys;print(sys.prefix)')/include ; export PYLIBS="$($PYTHON -c 'import sys;print("-L%s/bin -l%s" % (sys.prefix, "pypy-c" if sys.version_info < (3,) else "pypy3-c"))')" ; fi # Find the Ruby executable with version $RUBYLIBVER - rvm reinstall ruby-$RUBYLIBVER --binary - export RUBY="$(ls -d -1 "$HOME/.rvm/rubies/ruby-$RUBYLIBVER"*/bin/ruby | head -n 1)" # Set the linker in $CC so that it gets used everywhere - if [ -n "$LINKER" ]; then CC="$CC -fuse-ld=$LINKER" ; fi # Show variables and versions (to help debugging) - echo "$CC" ; $CC --version - echo "$PYTHON" ; $PYTHON --version - echo "$RUBY" ; $RUBY --version # If TEST_FLAGS_OVERRIDE is defined, test that overriding CFLAGS, LDFLAGS and other variables works fine - if [ -n "$TEST_FLAGS_OVERRIDE" ]; then EXPLICIT_MAKE_VARS="CFLAGS=-I$DESTDIR/usr/include LDFLAGS=-L$DESTDIR/usr/lib LDLIBS= CPPFLAGS=" ; fi script: # Start by installing everything into $DESTDIR - make install $EXPLICIT_MAKE_VARS -k - make install-pywrap $EXPLICIT_MAKE_VARS -k - make install-rubywrap $EXPLICIT_MAKE_VARS -k # Now that everything is installed, run "make all" to build everything which may have not been built - make all $EXPLICIT_MAKE_VARS -k # Set up environment variables for the tests - . ./scripts/env_use_destdir # Show variables (to help debugging issues) - echo "$LD_LIBRARY_PATH" - echo "$PATH" - echo "$PYTHONPATH" - echo "$RUBYLIB" # Run tests - make test $EXPLICIT_MAKE_VARS # Test Python and Ruby wrappers - $PYTHON -c 'import selinux;import selinux.audit2why;import semanage;print(selinux.is_selinux_enabled())' - $RUBY -e 'require "selinux";require "semanage";puts Selinux::is_selinux_enabled()' # Run Python linter - PATH="$VIRTUAL_ENV/bin:$PATH" ./scripts/run-flake8 # Remove every installed files - rm -rf "$DESTDIR" # Test that "git status" looks clean, or print a clear error message - |- git status --short | sed -n 's/^??/error: missing .gitignore entry for/p' | (! grep '^') # Clean up everything and show which file would be added to "make clean" - make clean distclean $EXPLICIT_MAKE_VARS - |- git ls-files --ignored --others --exclude-standard | sed 's/^/error: "make clean distclean" did not remove /' | (! grep '^') # Do not spam by email so long as the build succeeds notifications: email: on_success: never Android.bp0100644 0000000 0000000 00000000121 13756670063 011517 0ustar000000000 0000000 subdirs = [ "checkpolicy", "libselinux", "libsepol", "secilc", ] CleanSpec.mk0100644 0000000 0000000 00000000466 13756670063 012016 0ustar000000000 0000000 # This empty CleanSpec.mk file will prevent the build system # from descending into subdirs. # $(call add-clean-step, rm -rf $(OUT_DIR)/host/linux-x86/bin/audit2allow) $(call add-clean-step, rm -rf $(OUT_DIR)/host/linux-x86/bin/audit2why) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib/libselinux.so) MODULE_LICENSE_GPL0100644 0000000 0000000 00000000000 13756670063 012364 0ustar000000000 0000000 Makefile0100644 0000000 0000000 00000002224 13756670063 011262 0ustar000000000 0000000 PREFIX ?= /usr OPT_SUBDIRS ?= dbus gui mcstrans python restorecond sandbox semodule-utils SUBDIRS=libsepol libselinux libsemanage checkpolicy secilc policycoreutils $(OPT_SUBDIRS) PYSUBDIRS=libselinux libsemanage DISTCLEANSUBDIRS=libselinux libsemanage ifeq ($(DEBUG),1) export CFLAGS = -g3 -O0 -gdwarf-2 -fno-strict-aliasing -Wall -Wshadow -Werror export LDFLAGS = -g else export CFLAGS ?= -O2 -Werror -Wall -Wextra \ -Wmissing-format-attribute \ -Wmissing-noreturn \ -Wpointer-arith \ -Wshadow \ -Wstrict-prototypes \ -Wundef \ -Wunused \ -Wwrite-strings endif ifneq ($(DESTDIR),) LIBDIR ?= $(DESTDIR)$(PREFIX)/lib LIBSEPOLA ?= $(LIBDIR)/libsepol.a CFLAGS += -I$(DESTDIR)$(PREFIX)/include LDFLAGS += -L$(DESTDIR)$(PREFIX)/lib -L$(LIBDIR) export CFLAGS export LDFLAGS export LIBSEPOLA endif all install relabel clean test indent: @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done install-pywrap install-rubywrap swigify: @for subdir in $(PYSUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done distclean: @for subdir in $(DISTCLEANSUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done NOTICE0100644 0000000 0000000 00000324125 13756670063 010535 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, 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. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, 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. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. All files are licensed under the FreeBSD license, excepet for thid party components, which are subject to their respective licenses as specified in their source files. FreeBSD License Copyright 2011 Tresys Technology, LLC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Tresys Technology, LLC. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. OWNERS0100644 0000000 0000000 00000000065 13756670063 010563 0ustar000000000 0000000 jeffv@google.com jgalenson@google.com nnk@google.com README0100644 0000000 0000000 00000002167 13756670063 010510 0ustar000000000 0000000 Please submit all bug reports and patches to selinux@vger.kernel.org. Subscribe by sending "subscribe selinux" in the body of an email to majordomo@vger.kernel.org. Build dependencies on Fedora: yum install audit-libs-devel bison bzip2-devel dbus-devel dbus-glib-devel flex flex-devel flex-static glib2-devel libcap-devel libcap-ng-devel pam-devel pcre-devel python3-devel python3-setools swig xmlto redhat-rpm-config To build and install everything under a private directory, run: make DESTDIR=~/obj install install-pywrap To install as the default system libraries and binaries (overwriting any previously installed ones - dangerous!), on x86_64, run: make LIBDIR=/usr/lib64 SHLIBDIR=/lib64 install install-pywrap relabel or on x86 (32-bit), run: make install install-pywrap relabel This may render your system unusable if the upstream SELinux userspace lacks library functions or other dependencies relied upon by your distribution. If it breaks, you get to keep both pieces. To install libsepol on macOS (mainly for policy analysis): cd libsepol; make PREFIX=/usr/local install This requires GNU coreutils (brew install coreutils). README.android0100644 0000000 0000000 00000003267 13756670063 012131 0ustar000000000 0000000 This fork of Android differs in the following ways: - README.android - All Android.mk and Android.bp files - ALL MODULE_LICENSE_* files - libselinux/include/selinux/android.h - libselinux/src/android/android.c All other changes should be upstreamed to selinux as Android no longer carries changes outside of those files. The upstream project can be found at: https://github.com/SELinuxProject/selinux Thus, since all changes are in separate files, updates merged from upstream should occur with no merge conflicts. This fork differs from upstream libselinux in at least the following ways: * The Android fork omits compiling many of the src files and specifies custom build configurations. The exact details, are encoded in the Android.bp and Android.mk files. * The SELinux policy files are all located in / rather than under /etc/selinux since /etc is not available in Android until /system is mounted and use fixed paths, not dependent on /etc/selinux/config. * The kernel policy file (sepolicy in Android, policy.N in Linux) does not include a version suffix since Android does not need to support booting multiple kernels. * The policy loading logic does not support automatic downgrading of the kernel policy file to a version known to the kernel, since this requires libsepol on the device and is only needed to support mixing and matching kernels and userspace easily. * restorecon functionality, including recursive restorecon, has been been upstreamed as selinux_restorecon(), but there are residual differences between it and selinux_android_restorecon(). * Support for seapp_contexts, a new Android-specific SELinux configuration file has been added within android.c. checkpolicy/0040755 0000000 0000000 00000000000 13756670063 012122 5ustar000000000 0000000 checkpolicy/.gitignore0100644 0000000 0000000 00000000061 13756670063 014104 0ustar000000000 0000000 checkmodule checkpolicy lex.yy.c y.tab.c y.tab.h checkpolicy/Android.bp0100644 0000000 0000000 00000000750 13756670063 014024 0ustar000000000 0000000 common_CFLAGS = [ "-Wall", "-Werror", "-Wshadow", ] cc_binary_host { name: "checkpolicy", cflags: common_CFLAGS, srcs: [ "policy_parse.y", "policy_scan.l", "queue.c", "module_compiler.c", "parse_util.c", "policy_define.c", "checkpolicy.c", ], static_libs: ["libsepol"], } cc_binary_host { name: "dispol", cflags: common_CFLAGS, srcs: ["test/dispol.c"], static_libs: ["libsepol"], } checkpolicy/COPYING0100644 0000000 0000000 00000043131 13756670063 013154 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. checkpolicy/Makefile0100644 0000000 0000000 00000003700 13756670063 013557 0ustar000000000 0000000 # # Makefile for building the checkpolicy program # LINGUAS ?= ru PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/share/man TARGETS = checkpolicy checkmodule LEX = flex YACC = bison -y CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there # is no need to define a value for LDLIBS_LIBSEPOLA ifeq ($(LIBSEPOLA),) LDLIBS_LIBSEPOLA := -l:libsepol.a endif CHECKOBJS = y.tab.o lex.yy.o queue.o module_compiler.o parse_util.o \ policy_define.o CHECKPOLOBJS = $(CHECKOBJS) checkpolicy.o CHECKMODOBJS = $(CHECKOBJS) checkmodule.o GENERATED=lex.yy.c y.tab.c y.tab.h all: $(TARGETS) $(MAKE) -C test checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< y.tab.o: y.tab.c $(CC) $(filter-out -Werror, $(CFLAGS)) -o $@ -c $< lex.yy.o: lex.yy.c $(CC) $(filter-out -Werror, $(CFLAGS)) -o $@ -c $< y.tab.c: policy_parse.y $(YACC) -d policy_parse.y lex.yy.c: policy_scan.l y.tab.c $(LEX) policy_scan.l install: all -mkdir -p $(DESTDIR)$(BINDIR) -mkdir -p $(DESTDIR)$(MANDIR)/man8 install -m 755 $(TARGETS) $(DESTDIR)$(BINDIR) install -m 644 checkpolicy.8 $(DESTDIR)$(MANDIR)/man8 install -m 644 checkmodule.8 $(DESTDIR)$(MANDIR)/man8 for lang in $(LINGUAS) ; do \ if [ -e $${lang} ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/man8 ; \ install -m 644 $${lang}/*.8 $(DESTDIR)$(MANDIR)/$${lang}/man8 ; \ fi ; \ done relabel: install /sbin/restorecon $(DESTDIR)$(BINDIR)/checkpolicy /sbin/restorecon $(DESTDIR)$(BINDIR)/checkmodule clean: -rm -f $(TARGETS) $(CHECKPOLOBJS) $(CHECKMODOBJS) y.tab.c y.tab.h lex.yy.c $(MAKE) -C test clean indent: ../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch])) checkpolicy/VERSION0100644 0000000 0000000 00000000004 13756670063 013161 0ustar000000000 0000000 2.9 checkpolicy/checkmodule.80100644 0000000 0000000 00000004271 13756670063 014477 0ustar000000000 0000000 .TH CHECKMODULE 8 .SH NAME checkmodule \- SELinux policy module compiler .SH SYNOPSIS .B checkmodule .I "[\-h] [\-b] [\-C] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]" .SH "DESCRIPTION" This manual page describes the .BR checkmodule command. .PP .B checkmodule is a program that checks and compiles a SELinux security policy module into a binary representation. It can generate either a base policy module (default) or a non-base policy module (\-m option); typically, you would build a non-base policy module to add to an existing module store that already has a base module provided by the base policy. Use semodule_package to combine this module with its optional file contexts to create a policy package, and then use semodule to install the module package into the module store and load the resulting policy. .SH OPTIONS .TP .B \-b,\-\-binary Read an existing binary policy module file rather than a source policy module file. This option is a development/debugging aid. .TP .B \-C,\-\-cil Write CIL policy file rather than binary policy file. .TP .B \-h,\-\-help Print usage. .TP .B \-m Generate a non-base policy module. .TP .B \-M,\-\-mls Enable the MLS/MCS support when checking and compiling the policy module. .TP .B \-V,\-\-version Show policy versions created by this program. Note that you cannot currently build older versions. .TP .B \-o,\-\-output filename Write a binary policy module file to the specified filename. Otherwise, checkmodule will only check the syntax of the module source file and will not generate a binary module at all. .TP .B \-U,\-\-handle-unknown Specify how the kernel should handle unknown classes or permissions (deny, allow or reject). .SH EXAMPLE .nf # Build a MLS/MCS-enabled non-base policy module. $ checkmodule \-M \-m httpd.te \-o httpd.mod .fi .SH "SEE ALSO" .B semodule(8), semodule_package(8) SELinux documentation at http://www.nsa.gov/research/selinux, especially "Configuring the SELinux Policy". .SH AUTHOR This manual page was copied from the checkpolicy man page written by Arpad Magosanyi , and edited by Dan Walsh . The program was written by Stephen Smalley . checkpolicy/checkmodule.c0100644 0000000 0000000 00000020142 13756670063 014545 0ustar000000000 0000000 /* * Authors: Joshua Brindle * Karl MacMillan * Jason Tang * * * Copyright (C) 2004-5 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "queue.h" #include "checkpolicy.h" #include "parse_util.h" extern char *optarg; extern int optind; static sidtab_t sidtab; extern int mlspol; static int handle_unknown = SEPOL_DENY_UNKNOWN; static const char *txtfile = "policy.conf"; static const char *binfile = "policy"; unsigned int policy_type = POLICY_BASE; unsigned int policyvers = MOD_POLICYDB_VERSION_MAX; static int read_binary_policy(policydb_t * p, const char *file, const char *progname) { int fd; struct stat sb; void *map; struct policy_file f, *fp; fd = open(file, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", file, strerror(errno)); return -1; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", file, strerror(errno)); close(fd); return -1; } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", file, strerror(errno)); return -1; } policy_file_init(&f); f.type = PF_USE_MEMORY; f.data = map; f.len = sb.st_size; fp = &f; if (policydb_init(p)) { fprintf(stderr, "%s: policydb_init: Out of memory!\n", progname); return -1; } if (policydb_read(p, fp, 1)) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); return -1; } /* Check Policy Consistency */ if (p->mls) { if (!mlspol) { fprintf(stderr, "%s: MLS policy, but non-MLS" " is specified\n", progname); return -1; } } else { if (mlspol) { fprintf(stderr, "%s: non-MLS policy, but MLS" " is specified\n", progname); return -1; } } return 0; } static int write_binary_policy(policydb_t * p, FILE *outfp) { struct policy_file pf; p->policy_type = policy_type; p->policyvers = policyvers; p->handle_unknown = handle_unknown; policy_file_init(&pf); pf.type = PF_USE_STDIO; pf.fp = outfp; return policydb_write(p, &pf); } static __attribute__((__noreturn__)) void usage(const char *progname) { printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname); printf("Build base and policy modules.\n"); printf("Options:\n"); printf(" INPUT build module from INPUT (else read from \"%s\")\n", txtfile); printf(" -V show policy versions created by this program\n"); printf(" -b treat input as a binary policy file\n"); printf(" -C output CIL policy instead of binary policy\n"); printf(" -h print usage\n"); printf(" -U OPTION How to handle unknown classes and permissions\n"); printf(" deny: Deny unknown kernel checks\n"); printf(" reject: Reject loading of policy with unknowns\n"); printf(" allow: Allow unknown kernel checks\n"); printf(" -m build a policy module instead of a base module\n"); printf(" -M enable MLS policy\n"); printf(" -o FILE write module to FILE (else just check syntax)\n"); exit(1); } int main(int argc, char **argv) { const char *file = txtfile, *outfile = NULL; unsigned int binary = 0, cil = 0; int ch; int show_version = 0; policydb_t modpolicydb; struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"output", required_argument, NULL, 'o'}, {"binary", no_argument, NULL, 'b'}, {"version", no_argument, NULL, 'V'}, {"handle-unknown", required_argument, NULL, 'U'}, {"mls", no_argument, NULL, 'M'}, {"cil", no_argument, NULL, 'C'}, {NULL, 0, NULL, 0} }; while ((ch = getopt_long(argc, argv, "ho:bVU:mMC", long_options, NULL)) != -1) { switch (ch) { case 'h': usage(argv[0]); break; case 'o': outfile = optarg; break; case 'b': binary = 1; file = binfile; break; case 'V': show_version = 1; break; case 'U': if (!strcasecmp(optarg, "deny")) { handle_unknown = DENY_UNKNOWN; break; } if (!strcasecmp(optarg, "reject")) { handle_unknown = REJECT_UNKNOWN; break; } if (!strcasecmp(optarg, "allow")) { handle_unknown = ALLOW_UNKNOWN; break; } usage(argv[0]); case 'm': policy_type = POLICY_MOD; policyvers = MOD_POLICYDB_VERSION_MAX; break; case 'M': mlspol = 1; break; case 'C': cil = 1; break; default: usage(argv[0]); } } if (show_version) { printf("Module versions %d-%d\n", MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); exit(0); } if (handle_unknown && (policy_type != POLICY_BASE)) { fprintf(stderr, "%s: Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]); exit(1); } if (binary && (policy_type != POLICY_BASE)) { fprintf(stderr, "%s: -b and -m are incompatible with each other.\n", argv[0]); exit(1); } if (optind != argc) { file = argv[optind++]; if (optind != argc) usage(argv[0]); } /* Set policydb and sidtab used by libsepol service functions to my structures, so that I can directly populate and manipulate them. */ sepol_set_policydb(&modpolicydb); sepol_set_sidtab(&sidtab); if (binary) { if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) { exit(1); } } else { if (policydb_init(&modpolicydb)) { fprintf(stderr, "%s: out of memory!\n", argv[0]); return -1; } modpolicydb.policy_type = policy_type; modpolicydb.mls = mlspol; modpolicydb.handle_unknown = handle_unknown; if (read_source_policy(&modpolicydb, file, argv[0]) == -1) { exit(1); } if (hierarchy_check_constraints(NULL, &modpolicydb)) { return -1; } } if (policy_type != POLICY_BASE && outfile) { char *mod_name = modpolicydb.name; char *out_path = strdup(outfile); if (out_path == NULL) { fprintf(stderr, "%s: out of memory\n", argv[0]); exit(1); } char *out_name = basename(out_path); char *separator = strrchr(out_name, '.'); if (separator) { *separator = '\0'; } if (strcmp(mod_name, out_name) != 0) { fprintf(stderr, "%s: Module name %s is different than the output base filename %s\n", argv[0], mod_name, out_name); exit(1); } free(out_path); } if (modpolicydb.policy_type == POLICY_BASE && !cil) { /* Verify that we can successfully expand the base module. */ policydb_t kernpolicydb; if (policydb_init(&kernpolicydb)) { fprintf(stderr, "%s: policydb_init failed\n", argv[0]); exit(1); } if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) { fprintf(stderr, "%s: link modules failed\n", argv[0]); exit(1); } if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) { fprintf(stderr, "%s: expand module failed\n", argv[0]); exit(1); } policydb_destroy(&kernpolicydb); } if (policydb_load_isids(&modpolicydb, &sidtab)) exit(1); sepol_sidtab_destroy(&sidtab); if (outfile) { FILE *outfp = fopen(outfile, "w"); if (!outfp) { perror(outfile); exit(1); } if (!cil) { if (write_binary_policy(&modpolicydb, outfp) != 0) { fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); exit(1); } } else { if (sepol_module_policydb_to_cil(outfp, &modpolicydb, 0) != 0) { fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); exit(1); } } fclose(outfp); } else if (cil) { fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]); exit(1); } policydb_destroy(&modpolicydb); return 0; } /* FLASK */ checkpolicy/checkpolicy.80100644 0000000 0000000 00000004002 13756670063 014501 0ustar000000000 0000000 .TH CHECKPOLICY 8 .SH NAME checkpolicy \- SELinux policy compiler .SH SYNOPSIS .B checkpolicy .I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file] [\-S] [\-t target_platform (selinux,xen)] [\-V] [input_file]" .br .SH "DESCRIPTION" This manual page describes the .BR checkpolicy command. .PP .B checkpolicy is a program that checks and compiles a SELinux security policy configuration into a binary representation that can be loaded into the kernel. If no input file name is specified, checkpolicy will attempt to read from policy.conf or policy, depending on whether the \-b flag is specified. .SH OPTIONS .TP .B \-b,\-\-binary Read an existing binary policy file rather than a source policy.conf file. .TP .B \-F,\-\-conf Write policy.conf file rather than binary policy file. Can only be used with binary policy file. .TP .B \-C,\-\-cil Write CIL policy file rather than binary policy file. .TP .B \-d,\-\-debug Enter debug mode after loading the policy. .TP .B \-U,\-\-handle-unknown Specify how the kernel should handle unknown classes or permissions (deny, allow or reject). .TP .B \-M,\-\-mls Enable the MLS policy when checking and compiling the policy. .TP .B \-c policyvers Specify the policy version, defaults to the latest. .TP .B \-o,\-\-output filename Write a binary policy file to the specified filename. .TP .B \-S,\-\-sort Sort ocontexts before writing out the binary policy. This option makes output of checkpolicy consistent with binary policies created by semanage and secilc. .TP .B \-t,\-\-target Specify the target platform (selinux or xen). .TP .B \-V,\-\-version Show version information. .TP .B \-h,\-\-help Show usage information. .SH "SEE ALSO" SELinux documentation at http://www.nsa.gov/research/selinux, especially "Configuring the SELinux Policy". .SH AUTHOR This manual page was written by Arpad Magosanyi , and edited by Stephen Smalley . The program was written by Stephen Smalley . checkpolicy/checkpolicy.c0100644 0000000 0000000 00000072446 13756670063 014575 0ustar000000000 0000000 /* * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Karl MacMillan * * Added conditional policy language extensions * * Updated: James Morris * * Added IPv6 support. * * Updated: Joshua Brindle * Karl MacMillan * Jason Tang * * Policy Module support. * * Copyright (C) 2017 Mellanox Technologies Inc. * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2005 Tresys Technology, LLC * Copyright (C) 2003 Red Hat, Inc., James Morris * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* FLASK */ /* * checkpolicy * * Load and check a policy configuration. * * A policy configuration is created in a text format, * and then compiled into a binary format for use by * the security server. By default, checkpolicy reads * the text format. If '-b' is specified, then checkpolicy * reads the binary format instead. * * If '-o output_file' is specified, then checkpolicy * writes the binary format version of the configuration * to the specified output file. * * If '-d' is specified, then checkpolicy permits the user * to interactively test the security server functions with * the loaded policy configuration. * * If '-c' is specified, then the supplied parameter is used to * determine which policy version to use for generating binary * policy. This is for compatibility with older kernels. If any * booleans or conditional rules are thrown away a warning is printed. */ #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "queue.h" #include "checkpolicy.h" #include "parse_util.h" extern char *optarg; extern int optind; static policydb_t policydb; static sidtab_t sidtab; extern policydb_t *policydbp; extern int mlspol; static int handle_unknown = SEPOL_DENY_UNKNOWN; static const char *txtfile = "policy.conf"; static const char *binfile = "policy"; unsigned int policyvers = POLICYDB_VERSION_MAX; static __attribute__((__noreturn__)) void usage(const char *progname) { printf ("usage: %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M] " "[-c policyvers (%d-%d)] [-o output_file] [-S] " "[-t target_platform (selinux,xen)] [-V] [input_file]\n", progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); exit(1); } #define FGETS(out, size, in) \ if (fgets(out,size,in)==NULL) { \ fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\ strerror(errno)); \ exit(1);\ } static int print_sid(sepol_security_id_t sid, context_struct_t * context __attribute__ ((unused)), void *data __attribute__ ((unused))) { sepol_security_context_t scontext; size_t scontext_len; int rc; rc = sepol_sid_to_context(sid, &scontext, &scontext_len); if (rc) printf("sid %d -> error %d\n", sid, rc); else { printf("sid %d -> scontext %s\n", sid, scontext); free(scontext); } return 0; } struct val_to_name { unsigned int val; char *name; }; static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) { struct val_to_name *v = p; perm_datum_t *perdatum; perdatum = (perm_datum_t *) datum; if (v->val == perdatum->s.value) { v->name = key; return 1; } return 0; } #ifdef EQUIVTYPES static int insert_type_rule(avtab_key_t * k, avtab_datum_t * d, struct avtab_node *type_rules) { struct avtab_node *p, *c, *n; for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) { /* * Find the insertion point, keeping the list * ordered by source type, then target type, then * target class. */ if (k->source_type < c->key.source_type) break; if (k->source_type == c->key.source_type && k->target_type < c->key.target_type) break; if (k->source_type == c->key.source_type && k->target_type == c->key.target_type && k->target_class < c->key.target_class) break; } /* Insert the rule */ n = malloc(sizeof(struct avtab_node)); if (!n) { fprintf(stderr, "out of memory\n"); exit(1); } n->key = *k; n->datum = *d; n->next = p->next; p->next = n; return 0; } static int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args) { struct avtab_node *type_rules = args; if (d->specified & AVTAB_ALLOWED) { /* * Insert the rule into the lists for both * the source type and the target type. */ if (insert_type_rule(k, d, &type_rules[k->source_type - 1])) return -1; if (insert_type_rule(k, d, &type_rules[k->target_type - 1])) return -1; } return 0; } static void free_type_rules(struct avtab_node *l) { struct avtab_node *tmp; while (l) { tmp = l; l = l->next; free(tmp); } } static int identify_equiv_types(void) { struct avtab_node *type_rules, *l1, *l2; int i, j; /* * Create a list of access vector rules for each type * from the access vector table. */ type_rules = malloc(sizeof(struct avtab_node) * policydb.p_types.nprim); if (!type_rules) { fprintf(stderr, "out of memory\n"); exit(1); } memset(type_rules, 0, sizeof(struct avtab_node) * policydb.p_types.nprim); if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules)) exit(1); /* * Compare the type lists and identify equivalent types. */ for (i = 0; i < policydb.p_types.nprim - 1; i++) { if (!type_rules[i].next) continue; for (j = i + 1; j < policydb.p_types.nprim; j++) { for (l1 = type_rules[i].next, l2 = type_rules[j].next; l1 && l2; l1 = l1->next, l2 = l2->next) { if (l2->key.source_type == (j + 1)) { if (l1->key.source_type != (i + 1)) break; } else { if (l1->key.source_type != l2->key.source_type) break; } if (l2->key.target_type == (j + 1)) { if (l1->key.target_type != (i + 1)) break; } else { if (l1->key.target_type != l2->key.target_type) break; } if (l1->key.target_class != l2->key.target_class || l1->datum.allowed != l2->datum.allowed) break; } if (l1 || l2) continue; free_type_rules(type_rules[j].next); type_rules[j].next = NULL; printf("Types %s and %s are equivalent.\n", policydb.p_type_val_to_name[i], policydb.p_type_val_to_name[j]); } free_type_rules(type_rules[i].next); type_rules[i].next = NULL; } free(type_rules); return 0; } #endif extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av); int display_bools(void) { uint32_t i; for (i = 0; i < policydbp->p_bools.nprim; i++) { printf("%s : %d\n", policydbp->p_bool_val_to_name[i], policydbp->bool_val_to_struct[i]->state); } return 0; } void display_expr(cond_expr_t * exp) { cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: printf("%s ", policydbp->p_bool_val_to_name[cur->bool - 1]); break; case COND_NOT: printf("! "); break; case COND_OR: printf("|| "); break; case COND_AND: printf("&& "); break; case COND_XOR: printf("^ "); break; case COND_EQ: printf("== "); break; case COND_NEQ: printf("!= "); break; default: printf("error!"); break; } } } int display_cond_expressions(void) { cond_node_t *cur; for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) { printf("expression: "); display_expr(cur->expr); printf("current state: %d\n", cur->cur_state); } return 0; } int change_bool(char *name, int state) { cond_bool_datum_t *bool; bool = hashtab_search(policydbp->p_bools.table, name); if (bool == NULL) { printf("Could not find bool %s\n", name); return -1; } bool->state = state; evaluate_conds(policydbp); return 0; } static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg __attribute__ ((unused))) { level_datum_t *levdatum = (level_datum_t *) datum; if (!levdatum->isalias && !levdatum->defined) { fprintf(stderr, "Error: sensitivity %s was not used in a level definition!\n", key); return -1; } return 0; } int main(int argc, char **argv) { policydb_t parse_policy; sepol_security_class_t tclass; sepol_security_id_t ssid, tsid, *sids, oldsid, newsid, tasksid; sepol_security_context_t scontext; struct sepol_av_decision avd; class_datum_t *cladatum; const char *file = txtfile; char ans[80 + 1], *outfile = NULL, *path, *fstype; size_t scontext_len, pathlen; unsigned int i; unsigned int protocol, port; unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0; struct val_to_name v; int ret, ch, fd, target = SEPOL_TARGET_SELINUX; unsigned int nel, uret; struct stat sb; void *map; FILE *outfp = NULL; char *name; int state; int show_version = 0; char *reason_buf = NULL; unsigned int reason; int flags; struct policy_file pf; struct option long_options[] = { {"output", required_argument, NULL, 'o'}, {"target", required_argument, NULL, 't'}, {"binary", no_argument, NULL, 'b'}, {"debug", no_argument, NULL, 'd'}, {"version", no_argument, NULL, 'V'}, {"handle-unknown", required_argument, NULL, 'U'}, {"mls", no_argument, NULL, 'M'}, {"cil", no_argument, NULL, 'C'}, {"conf",no_argument, NULL, 'F'}, {"sort", no_argument, NULL, 'S'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:h", long_options, NULL)) != -1) { switch (ch) { case 'o': outfile = optarg; break; case 't': if (!strcasecmp(optarg, "Xen")) target = SEPOL_TARGET_XEN; else if (!strcasecmp(optarg, "SELinux")) target = SEPOL_TARGET_SELINUX; else{ fprintf(stderr, "%s: Unknown target platform:" "%s\n", argv[0], optarg); exit(1); } break; case 'b': binary = 1; file = binfile; break; case 'd': debug = 1; break; case 'V': show_version = 1; break; case 'U': if (!strcasecmp(optarg, "deny")) { handle_unknown = DENY_UNKNOWN; break; } if (!strcasecmp(optarg, "allow")) { handle_unknown = ALLOW_UNKNOWN; break; } if (!strcasecmp(optarg, "reject")) { handle_unknown = REJECT_UNKNOWN; break; } usage(argv[0]); case 'S': sort = 1; break; case 'M': mlspol = 1; break; case 'C': cil = 1; break; case 'F': conf = 1; break; case 'c':{ long int n; errno = 0; n = strtol(optarg, NULL, 10); if (errno) { fprintf(stderr, "Invalid policyvers specified: %s\n", optarg); usage(argv[0]); exit(1); } if (n < POLICYDB_VERSION_MIN || n > POLICYDB_VERSION_MAX) { fprintf(stderr, "policyvers value %ld not in range %d-%d\n", n, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); usage(argv[0]); exit(1); } if (policyvers != n) policyvers = n; break; } case 'h': default: usage(argv[0]); } } if (show_version) { printf("%d (compatibility range %d-%d)\n", policyvers, POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN); exit(0); } if (optind != argc) { file = argv[optind++]; if (optind != argc) usage(argv[0]); } /* Set policydb and sidtab used by libsepol service functions to my structures, so that I can directly populate and manipulate them. */ sepol_set_policydb(&policydb); sepol_set_sidtab(&sidtab); if (cil && conf) { fprintf(stderr, "Can't convert to CIL and policy.conf at the same time\n"); exit(1); } if (binary) { fd = open(file, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", file, strerror(errno)); exit(1); } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", file, strerror(errno)); exit(1); } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", file, strerror(errno)); exit(1); } policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = map; pf.len = sb.st_size; if (policydb_init(&policydb)) { fprintf(stderr, "%s: policydb_init: Out of memory!\n", argv[0]); exit(1); } ret = policydb_read(&policydb, &pf, 1); if (ret) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", argv[0]); exit(1); } policydbp = &policydb; /* Check Policy Consistency */ if (policydbp->mls) { if (!mlspol) { fprintf(stderr, "%s: MLS policy, but non-MLS" " is specified\n", argv[0]); exit(1); } } else { if (mlspol) { fprintf(stderr, "%s: non-MLS policy, but MLS" " is specified\n", argv[0]); exit(1); } } } else { if (conf) { fprintf(stderr, "Can only generate policy.conf from binary policy\n"); exit(1); } if (policydb_init(&parse_policy)) exit(1); /* We build this as a base policy first since that is all the parser understands */ parse_policy.policy_type = POLICY_BASE; policydb_set_target_platform(&parse_policy, target); /* Let sepol know if we are dealing with MLS support */ parse_policy.mls = mlspol; parse_policy.handle_unknown = handle_unknown; policydbp = &parse_policy; if (read_source_policy(policydbp, file, "checkpolicy") < 0) exit(1); if (hashtab_map(policydbp->p_levels.table, check_level, NULL)) exit(1); /* Linking takes care of optional avrule blocks */ if (link_modules(NULL, policydbp, NULL, 0, 0)) { fprintf(stderr, "Error while resolving optionals\n"); exit(1); } if (!cil) { if (policydb_init(&policydb)) { fprintf(stderr, "%s: policydb_init failed\n", argv[0]); exit(1); } if (expand_module(NULL, policydbp, &policydb, 0, 1)) { fprintf(stderr, "Error while expanding policy\n"); exit(1); } policydb_destroy(policydbp); policydbp = &policydb; } } if (policydb_load_isids(&policydb, &sidtab)) exit(1); if (outfile) { outfp = fopen(outfile, "w"); if (!outfp) { perror(outfile); exit(1); } policydb.policyvers = policyvers; if (!cil) { if (!conf) { policydb.policy_type = POLICY_KERN; policy_file_init(&pf); pf.type = PF_USE_STDIO; pf.fp = outfp; if (sort) { ret = policydb_sort_ocontexts(&policydb); if (ret) { fprintf(stderr, "%s: error sorting ocontexts\n", argv[0]); exit(1); } } ret = policydb_write(&policydb, &pf); } else { ret = sepol_kernel_policydb_to_conf(outfp, policydbp); } if (ret) { fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); exit(1); } } else { if (binary) { ret = sepol_kernel_policydb_to_cil(outfp, policydbp); } else { ret = sepol_module_policydb_to_cil(outfp, policydbp, 1); } if (ret) { fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); exit(1); } } if (outfile) { fclose(outfp); } } else if (cil) { fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]); exit(1); } if (!debug) { policydb_destroy(&policydb); sepol_sidtab_destroy(&sidtab); exit(0); } menu: printf("\nSelect an option:\n"); printf("0) Call compute_access_vector\n"); printf("1) Call sid_to_context\n"); printf("2) Call context_to_sid\n"); printf("3) Call transition_sid\n"); printf("4) Call member_sid\n"); printf("5) Call change_sid\n"); printf("6) Call list_sids\n"); printf("7) Call load_policy\n"); printf("8) Call fs_sid\n"); printf("9) Call port_sid\n"); printf("a) Call netif_sid\n"); printf("b) Call node_sid\n"); printf("c) Call fs_use\n"); printf("d) Call genfs_sid\n"); printf("e) Call get_user_sids\n"); printf("f) display conditional bools\n"); printf("g) display conditional expressions\n"); printf("h) change a boolean value\n"); printf("i) display constraint expressions\n"); printf("j) display validatetrans expressions\n"); printf("k) Call ibpkey_sid\n"); printf("l) Call ibendport_sid\n"); #ifdef EQUIVTYPES printf("z) Show equivalent types\n"); #endif printf("m) Show menu again\n"); printf("q) Exit\n"); while (1) { printf("\nChoose: "); FGETS(ans, sizeof(ans), stdin); switch (ans[0]) { case '0': printf("source sid? "); FGETS(ans, sizeof(ans), stdin); ssid = atoi(ans); printf("target sid? "); FGETS(ans, sizeof(ans), stdin); tsid = atoi(ans); printf("target class? "); FGETS(ans, sizeof(ans), stdin); if (isdigit(ans[0])) { tclass = atoi(ans); if (!tclass || tclass > policydb.p_classes.nprim) { printf("\nNo such class.\n"); break; } cladatum = policydb.class_val_to_struct[tclass - 1]; } else { ans[strlen(ans) - 1] = 0; cladatum = (class_datum_t *) hashtab_search(policydb. p_classes. table, ans); if (!cladatum) { printf("\nNo such class\n"); break; } tclass = cladatum->s.value; } if (!cladatum->comdatum && !cladatum->permissions.nprim) { printf ("\nNo access vector definition for that class\n"); break; } ret = sepol_compute_av(ssid, tsid, tclass, 0, &avd); switch (ret) { case 0: printf("\nallowed {"); for (i = 1; i <= sizeof(avd.allowed) * 8; i++) { if (avd.allowed & (1 << (i - 1))) { v.val = i; ret = hashtab_map(cladatum-> permissions. table, find_perm, &v); if (!ret && cladatum->comdatum) { ret = hashtab_map (cladatum-> comdatum-> permissions.table, find_perm, &v); } if (ret) printf(" %s", v.name); } } printf(" }\n"); break; case -EINVAL: printf("\ninvalid sid\n"); break; default: printf("return code 0x%x\n", ret); } break; case '1': printf("sid? "); FGETS(ans, sizeof(ans), stdin); ssid = atoi(ans); ret = sepol_sid_to_context(ssid, &scontext, &scontext_len); switch (ret) { case 0: printf("\nscontext %s\n", scontext); free(scontext); break; case -EINVAL: printf("\ninvalid sid\n"); break; case -ENOMEM: printf("\nout of memory\n"); break; default: printf("return code 0x%x\n", ret); } break; case '2': printf("scontext? "); FGETS(ans, sizeof(ans), stdin); scontext_len = strlen(ans); ans[scontext_len - 1] = 0; ret = sepol_context_to_sid(ans, scontext_len, &ssid); switch (ret) { case 0: printf("\nsid %d\n", ssid); break; case -EINVAL: printf("\ninvalid context\n"); break; case -ENOMEM: printf("\nout of memory\n"); break; default: printf("return code 0x%x\n", ret); } break; case '3': case '4': case '5': ch = ans[0]; printf("source sid? "); FGETS(ans, sizeof(ans), stdin); ssid = atoi(ans); printf("target sid? "); FGETS(ans, sizeof(ans), stdin); tsid = atoi(ans); printf("object class? "); FGETS(ans, sizeof(ans), stdin); if (isdigit(ans[0])) { tclass = atoi(ans); if (!tclass || tclass > policydb.p_classes.nprim) { printf("\nNo such class.\n"); break; } } else { ans[strlen(ans) - 1] = 0; cladatum = (class_datum_t *) hashtab_search(policydb. p_classes. table, ans); if (!cladatum) { printf("\nNo such class\n"); break; } tclass = cladatum->s.value; } if (ch == '3') ret = sepol_transition_sid(ssid, tsid, tclass, &ssid); else if (ch == '4') ret = sepol_member_sid(ssid, tsid, tclass, &ssid); else ret = sepol_change_sid(ssid, tsid, tclass, &ssid); switch (ret) { case 0: printf("\nsid %d\n", ssid); break; case -EINVAL: printf("\ninvalid sid\n"); break; case -ENOMEM: printf("\nout of memory\n"); break; default: printf("return code 0x%x\n", ret); } break; case '6': sepol_sidtab_map(&sidtab, print_sid, 0); break; case '7': printf("pathname? "); FGETS(ans, sizeof(ans), stdin); pathlen = strlen(ans); ans[pathlen - 1] = 0; fd = open(ans, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", ans, strerror(errno)); break; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", ans, strerror(errno)); break; } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", ans, strerror(errno)); break; } ret = sepol_load_policy(map, sb.st_size); switch (ret) { case 0: printf("\nsuccess\n"); break; case -EINVAL: printf("\ninvalid policy\n"); break; case -ENOMEM: printf("\nout of memory\n"); break; default: printf("return code 0x%x\n", ret); } break; case '8': printf("fs kdevname? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; sepol_fs_sid(ans, &ssid, &tsid); printf("fs_sid %d default_file_sid %d\n", ssid, tsid); break; case '9': printf("protocol? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP")) protocol = IPPROTO_TCP; else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP")) protocol = IPPROTO_UDP; else if (!strcmp(ans, "dccp") || !strcmp(ans, "DCCP")) protocol = IPPROTO_DCCP; else if (!strcmp(ans, "sctp") || !strcmp(ans, "SCTP")) protocol = IPPROTO_SCTP; else { printf("unknown protocol\n"); break; } printf("port? "); FGETS(ans, sizeof(ans), stdin); port = atoi(ans); sepol_port_sid(0, 0, protocol, port, &ssid); printf("sid %d\n", ssid); break; case 'a': printf("netif name? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; sepol_netif_sid(ans, &ssid, &tsid); printf("if_sid %d default_msg_sid %d\n", ssid, tsid); break; case 'b':{ char *p; int family, len; struct in_addr addr4; struct in6_addr addr6; printf("protocol family? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; if (!strcasecmp(ans, "ipv4")) family = AF_INET; else if (!strcasecmp(ans, "ipv6")) family = AF_INET6; else { printf("unknown protocol family\n"); break; } printf("node address? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; if (family == AF_INET) { p = (char *)&addr4; len = sizeof(addr4); } else { p = (char *)&addr6; len = sizeof(addr6); } if (inet_pton(family, ans, p) < 1) { printf("error parsing address\n"); break; } sepol_node_sid(family, p, len, &ssid); printf("sid %d\n", ssid); break; } case 'c': printf("fstype? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; sepol_fs_use(ans, &uret, &ssid); switch (uret) { case SECURITY_FS_USE_XATTR: printf("use xattr\n"); break; case SECURITY_FS_USE_TRANS: printf("use transition SIDs\n"); break; case SECURITY_FS_USE_TASK: printf("use task SIDs\n"); break; case SECURITY_FS_USE_GENFS: printf("use genfs\n"); break; case SECURITY_FS_USE_NONE: printf("no labeling support\n"); break; } printf("sid %d\n", ssid); break; case 'd': printf("fstype? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; fstype = strdup(ans); printf("path? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; path = strdup(ans); printf("object class? "); FGETS(ans, sizeof(ans), stdin); if (isdigit(ans[0])) { tclass = atoi(ans); if (!tclass || tclass > policydb.p_classes.nprim) { printf("\nNo such class.\n"); break; } } else { ans[strlen(ans) - 1] = 0; cladatum = (class_datum_t *) hashtab_search(policydb. p_classes. table, ans); if (!cladatum) { printf("\nNo such class\n"); break; } tclass = cladatum->s.value; } sepol_genfs_sid(fstype, path, tclass, &ssid); printf("sid %d\n", ssid); free(fstype); free(path); break; case 'e': printf("from SID? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; ssid = atoi(ans); printf("username? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; ret = sepol_get_user_sids(ssid, ans, &sids, &nel); switch (ret) { case 0: if (!nel) printf("\nnone\n"); for (i = 0; i < nel; i++) print_sid(sids[i], NULL, NULL); free(sids); break; case -ENOMEM: printf("\nout of memory\n"); break; case -EINVAL: printf("\ninvalid argument\n"); break; default: printf("\nerror\n"); break; } break; case 'f': display_bools(); break; case 'g': display_cond_expressions(); break; case 'h': printf("name? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; name = malloc((strlen(ans) + 1) * sizeof(char)); if (name == NULL) { fprintf(stderr, "couldn't malloc string.\n"); break; } strcpy(name, ans); printf("state? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; if (atoi(ans)) state = 1; else state = 0; change_bool(name, state); free(name); break; case 'i': printf("source sid? "); FGETS(ans, sizeof(ans), stdin); ssid = atoi(ans); printf("target sid? "); FGETS(ans, sizeof(ans), stdin); tsid = atoi(ans); printf("target class? "); FGETS(ans, sizeof(ans), stdin); if (isdigit(ans[0])) { tclass = atoi(ans); if (!tclass || tclass > policydb.p_classes.nprim) { printf("\nNo such class.\n"); break; } cladatum = policydb.class_val_to_struct[tclass - 1]; } else { ans[strlen(ans) - 1] = 0; cladatum = (class_datum_t *) hashtab_search(policydb. p_classes. table, ans); if (!cladatum) { printf("\nNo such class\n"); break; } tclass = cladatum->s.value; } flags = SHOW_GRANTED; if (sepol_compute_av_reason_buffer(ssid, tsid, tclass, 0, &avd, &reason, &reason_buf, flags)) { printf("\nconstraint error\n"); break; } if (reason_buf) { printf("\nConstraint expressions:\n%s", reason_buf); free(reason_buf); } else { printf("\nNo constraints found.\n"); } break; case 'j': printf("old sid? "); FGETS(ans, sizeof(ans), stdin); oldsid = atoi(ans); printf("new sid? "); FGETS(ans, sizeof(ans), stdin); newsid = atoi(ans); printf("task sid? "); FGETS(ans, sizeof(ans), stdin); tasksid = atoi(ans); printf("target class? "); FGETS(ans, sizeof(ans), stdin); if (isdigit(ans[0])) { tclass = atoi(ans); if (!tclass || tclass > policydb.p_classes.nprim) { printf("\nNo such class.\n"); break; } cladatum = policydb.class_val_to_struct[tclass - 1]; } else { ans[strlen(ans) - 1] = 0; cladatum = (class_datum_t *) hashtab_search(policydb. p_classes. table, ans); if (!cladatum) { printf("\nNo such class\n"); break; } tclass = cladatum->s.value; } flags = SHOW_GRANTED; if (sepol_validate_transition_reason_buffer(oldsid, newsid, tasksid, tclass, &reason_buf, flags)) { printf("\nvalidatetrans error\n"); break; } if (reason_buf) { printf("\nValidatetrans expressions:\n%s", reason_buf); free(reason_buf); } else { printf( "\nNo validatetrans expressions found.\n"); } break; case 'k': { char *p; struct in6_addr addr6; uint64_t subnet_prefix; unsigned int pkey; printf("subnet prefix? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; p = (char *)&addr6; if (inet_pton(AF_INET6, ans, p) < 1) { printf("error parsing subnet prefix\n"); break; } memcpy(&subnet_prefix, p, sizeof(subnet_prefix)); printf("pkey? "); FGETS(ans, sizeof(ans), stdin); pkey = atoi(ans); sepol_ibpkey_sid(subnet_prefix, pkey, &ssid); printf("sid %d\n", ssid); } break; case 'l': printf("device name (eg. mlx4_0)? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; name = malloc((strlen(ans) + 1) * sizeof(char)); if (!name) { fprintf(stderr, "couldn't malloc string.\n"); break; } strcpy(name, ans); printf("port? "); FGETS(ans, sizeof(ans), stdin); port = atoi(ans); sepol_ibendport_sid(name, port, &ssid); printf("sid %d\n", ssid); free(name); break; #ifdef EQUIVTYPES case 'z': identify_equiv_types(); break; #endif case 'm': goto menu; case 'q': exit(0); break; default: printf("\nUnknown option %s.\n", ans); } } return 0; } /* FLASK */ checkpolicy/checkpolicy.h0100644 0000000 0000000 00000000527 13756670063 014571 0ustar000000000 0000000 #ifndef _CHECKPOLICY_H_ #define _CHECKPOLICY_H_ #include typedef struct te_assert { ebitmap_t stypes; ebitmap_t ttypes; ebitmap_t tclasses; int self; sepol_access_vector_t *avp; unsigned long line; struct te_assert *next; } te_assert_t; te_assert_t *te_assertions; extern unsigned int policyvers; #endif checkpolicy/module_compiler.c0100644 0000000 0000000 00000104373 13756670063 015452 0ustar000000000 0000000 /* Author : Joshua Brindle * Karl MacMillan * Jason Tang * Added support for binary policy modules * * Copyright (C) 2004 - 2005 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ #include #include #include #include #include #include #include #include "queue.h" #include "module_compiler.h" union stack_item_u { avrule_block_t *avrule; cond_list_t *cond_list; }; typedef struct scope_stack { union stack_item_u u; int type; /* for above union: 1 = avrule block, 2 = conditional */ avrule_decl_t *decl; /* if in an avrule block, which * declaration is current */ avrule_t *last_avrule; int in_else; /* if in an avrule block, within ELSE branch */ int require_given; /* 1 if this block had at least one require */ struct scope_stack *parent, *child; } scope_stack_t; extern policydb_t *policydbp; extern queue_t id_queue; extern int yyerror(const char *msg); __attribute__ ((format(printf, 1, 2))) extern void yyerror2(const char *fmt, ...); static int push_stack(int stack_type, ...); static void pop_stack(void); /* keep track of the last item added to the stack */ static scope_stack_t *stack_top = NULL; static avrule_block_t *last_block; static uint32_t next_decl_id = 1; static const char * const flavor_str[SYM_NUM] = { [SYM_COMMONS] = "common", [SYM_CLASSES] = "class", [SYM_ROLES] = "role", [SYM_TYPES] = "type", [SYM_USERS] = "user", [SYM_BOOLS] = "bool", [SYM_LEVELS] = "level", [SYM_CATS] = "cat" }; static void print_error_msg(int ret, uint32_t symbol_type) { switch (ret) { case -3: yyerror("Out of memory!"); break; case -2: yyerror2("Duplicate declaration of %s", flavor_str[symbol_type]); break; case -1: yyerror2("Could not declare %s here", flavor_str[symbol_type]); break; default: yyerror("Unknown error"); } } int define_policy(int pass, int module_header_given) { char *id; if (module_header_given) { if (policydbp->policy_type != POLICY_MOD) { yyerror ("Module specification found while not building a policy module.\n"); return -1; } if (pass == 2) { while ((id = queue_remove(id_queue)) != NULL) free(id); } else { id = (char *)queue_remove(id_queue); if (!id) { yyerror("no module name"); return -1; } policydbp->name = id; if ((policydbp->version = queue_remove(id_queue)) == NULL) { yyerror ("Expected a module version but none was found."); return -1; } } } else { if (policydbp->policy_type == POLICY_MOD) { yyerror ("Building a policy module, but no module specification found.\n"); return -1; } } /* the first declaration within the global avrule block will always have an id of 1 */ next_decl_id = 2; /* reset the scoping stack */ while (stack_top != NULL) { pop_stack(); } if (push_stack(1, policydbp->global, policydbp->global->branch_list) == -1) { return -1; } last_block = policydbp->global; return 0; } /* Given the current parse stack, returns 1 if a declaration or require would * be allowed here or 0 if not. For example, declarations and requirements are * not allowed in conditionals, so if there are any conditionals in the * current scope stack then this would return a 0. */ static int is_creation_allowed(void) { if (stack_top->type != 1 || stack_top->in_else) { return 0; } return 1; } /* Attempt to declare or require a symbol within the current scope. * Returns: * 0: Success - Symbol had not been previously created. * 1: Success - Symbol had already been created and caller must free datum. * -1: Failure - Symbol cannot be created here * -2: Failure - Duplicate declaration or type/attribute mismatch * -3: Failure - Out of memory or some other error */ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t scope) { avrule_decl_t *decl = stack_top->decl; int ret; if (!is_creation_allowed()) { return -1; } ret = symtab_insert(policydbp, symbol_type, key, datum, scope, decl->decl_id, dest_value); if (ret == 1 && dest_value) { symtab_datum_t *s = hashtab_search(policydbp->symtab[symbol_type].table, key); assert(s != NULL); if (symbol_type == SYM_LEVELS) { *dest_value = ((level_datum_t *)s)->level->sens; } else { *dest_value = s->value; } } else if (ret == -2) { return -2; } else if (ret < 0) { return -3; } return ret; } /* Attempt to declare a symbol within the current declaration. If * currently within a non-conditional and in a non-else branch then * insert the symbol, return 0 on success if symbol was undeclared. * For roles and users, it is legal to have multiple declarations; as * such return 1 to indicate that caller must free() the datum because * it was not added. If symbols may not be declared here return -1. * For duplicate declarations return -2. For all else, including out * of memory, return -3. Note that dest_value and datum_value might * not be restricted pointers. */ int declare_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value) { avrule_decl_t *decl = stack_top->decl; int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL); if (ret < 0) { return ret; } if (ebitmap_set_bit(decl->declared.scope + symbol_type, *datum_value - 1, 1)) { return -3; } return ret; } static int role_implicit_bounds(hashtab_t roles_tab, char *role_id, role_datum_t *role) { role_datum_t *bounds; char *bounds_id, *delim; delim = strrchr(role_id, '.'); if (!delim) return 0; /* no implicit boundary */ bounds_id = strdup(role_id); if (!bounds_id) { yyerror("out of memory"); return -1; } bounds_id[(size_t)(delim - role_id)] = '\0'; bounds = hashtab_search(roles_tab, bounds_id); if (!bounds) { yyerror2("role %s doesn't exist, is implicit bounds of %s", bounds_id, role_id); return -1; } if (!role->bounds) role->bounds = bounds->s.value; else if (role->bounds != bounds->s.value) { yyerror2("role %s has inconsistent bounds %s/%s", role_id, bounds_id, policydbp->p_role_val_to_name[role->bounds - 1]); return -1; } free(bounds_id); return 0; } static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role, char **key) { char *id = queue_remove(id_queue); role_datum_t *datum = NULL; int ret; uint32_t value; *role = NULL; *key = NULL; isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE; if (id == NULL) { yyerror("no role name"); return -1; } datum = malloc(sizeof(*datum)); if (datum == NULL) { yyerror("Out of memory!"); free(id); return -1; } role_datum_init(datum); datum->flavor = isattr; if (scope == SCOPE_DECL) { ret = declare_symbol(SYM_ROLES, id, datum, &value, &value); } else { ret = require_symbol(SYM_ROLES, id, datum, &value, &value); } datum->s.value = value; if (ret == 0) { *role = datum; *key = strdup(id); if (*key == NULL) { yyerror("Out of memory!"); return -1; } } else if (ret == 1) { *role = hashtab_search(policydbp->symtab[SYM_ROLES].table, id); if (*role && (isattr != (*role)->flavor)) { yyerror2("Identifier %s used as both an attribute and a role", id); free(id); role_datum_destroy(datum); free(datum); return -1; } *role = datum; *key = id; } else { print_error_msg(ret, SYM_ROLES); free(id); role_datum_destroy(datum); free(datum); } return ret; } role_datum_t *declare_role(unsigned char isattr) { char *key = NULL; role_datum_t *role = NULL; role_datum_t *dest_role = NULL; hashtab_t roles_tab; int ret, ret2; ret = create_role(SCOPE_DECL, isattr, &role, &key); if (ret < 0) { return NULL; } /* create a new role_datum_t for this decl, if necessary */ assert(stack_top->type == 1); if (stack_top->parent == NULL) { /* in parent, so use global symbol table */ roles_tab = policydbp->p_roles.table; } else { roles_tab = stack_top->decl->p_roles.table; } dest_role = hashtab_search(roles_tab, key); if (dest_role == NULL) { if (ret == 0) { dest_role = malloc(sizeof(*dest_role)); if (dest_role == NULL) { yyerror("Out of memory!"); free(key); return NULL; } role_datum_init(dest_role); dest_role->s.value = role->s.value; dest_role->flavor = role->flavor; } else { dest_role = role; } ret2 = role_implicit_bounds(roles_tab, key, dest_role); if (ret2 != 0) { free(key); role_datum_destroy(dest_role); free(dest_role); return NULL; } ret2 = hashtab_insert(roles_tab, key, dest_role); if (ret2 != 0) { yyerror("Out of memory!"); free(key); role_datum_destroy(dest_role); free(dest_role); return NULL; } } else { free(key); if (ret == 1) { role_datum_destroy(role); free(role); } } if (ret == 0) { ret2 = ebitmap_set_bit(&dest_role->dominates, dest_role->s.value - 1, 1); if (ret2 != 0) { yyerror("out of memory"); return NULL; } } return dest_role; } static int create_type(uint32_t scope, unsigned char isattr, type_datum_t **type) { char *id; type_datum_t *datum; int ret; uint32_t value = 0; *type = NULL; isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE; id = (char *)queue_remove(id_queue); if (!id) { yyerror("no type/attribute name?"); return -1; } if (strcmp(id, "self") == 0) { yyerror("\"self\" is a reserved type name."); free(id); return -1; } datum = malloc(sizeof(*datum)); if (!datum) { yyerror("Out of memory!"); free(id); return -1; } type_datum_init(datum); datum->primary = 1; datum->flavor = isattr; if (scope == SCOPE_DECL) { ret = declare_symbol(SYM_TYPES, id, datum, &value, &value); } else { ret = require_symbol(SYM_TYPES, id, datum, &value, &value); } if (ret == 0) { datum->s.value = value; *type = datum; } else if (ret == 1) { type_datum_destroy(datum); free(datum); *type = hashtab_search(policydbp->symtab[SYM_TYPES].table, id); if (*type && (isattr != (*type)->flavor)) { yyerror2("Identifier %s used as both an attribute and a type", id); free(id); return -1; } free(id); } else { print_error_msg(ret, SYM_TYPES); free(id); type_datum_destroy(datum); free(datum); } return ret; } type_datum_t *declare_type(unsigned char primary, unsigned char isattr) { type_datum_t *type = NULL; int ret = create_type(SCOPE_DECL, isattr, &type); if (ret == 0) { type->primary = primary; } return type; } static int user_implicit_bounds(hashtab_t users_tab, char *user_id, user_datum_t *user) { user_datum_t *bounds; char *bounds_id, *delim; delim = strrchr(user_id, '.'); if (!delim) return 0; /* no implicit boundary */ bounds_id = strdup(user_id); if (!bounds_id) { yyerror("out of memory"); return -1; } bounds_id[(size_t)(delim - user_id)] = '\0'; bounds = hashtab_search(users_tab, bounds_id); if (!bounds) { yyerror2("user %s doesn't exist, is implicit bounds of %s", bounds_id, user_id); return -1; } if (!user->bounds) user->bounds = bounds->s.value; else if (user->bounds != bounds->s.value) { yyerror2("user %s has inconsistent bounds %s/%s", user_id, bounds_id, policydbp->p_role_val_to_name[user->bounds - 1]); return -1; } free(bounds_id); return 0; } static int create_user(uint32_t scope, user_datum_t **user, char **key) { char *id = queue_remove(id_queue); user_datum_t *datum = NULL; int ret; uint32_t value; *user = NULL; *key = NULL; if (id == NULL) { yyerror("no user name"); return -1; } datum = malloc(sizeof(*datum)); if (datum == NULL) { yyerror("Out of memory!"); free(id); return -1; } user_datum_init(datum); if (scope == SCOPE_DECL) { ret = declare_symbol(SYM_USERS, id, datum, &value, &value); } else { ret = require_symbol(SYM_USERS, id, datum, &value, &value); } datum->s.value = value; if (ret == 0) { *user = datum; *key = strdup(id); if (*key == NULL) { yyerror("Out of memory!"); return -1; } } else if (ret == 1) { *user = datum; *key = id; } else { print_error_msg(ret, SYM_USERS); free(id); user_datum_destroy(datum); free(datum); } return ret; } user_datum_t *declare_user(void) { char *key = NULL; user_datum_t *user = NULL; user_datum_t *dest_user = NULL; hashtab_t users_tab; int ret, ret2; ret = create_user(SCOPE_DECL, &user, &key); if (ret < 0) { return NULL; } /* create a new user_datum_t for this decl, if necessary */ assert(stack_top->type == 1); if (stack_top->parent == NULL) { /* in parent, so use global symbol table */ users_tab = policydbp->p_users.table; } else { users_tab = stack_top->decl->p_users.table; } dest_user = hashtab_search(users_tab, key); if (dest_user == NULL) { if (ret == 0) { dest_user = malloc(sizeof(*dest_user)); if (dest_user == NULL) { yyerror("Out of memory!"); free(key); return NULL; } user_datum_init(dest_user); dest_user->s.value = user->s.value; } else { dest_user = user; } ret2 = user_implicit_bounds(users_tab, key, dest_user); if (ret2 != 0) { free(key); user_datum_destroy(dest_user); free(dest_user); return NULL; } ret2 = hashtab_insert(users_tab, key, dest_user); if (ret2 != 0) { yyerror("Out of memory!"); free(key); user_datum_destroy(dest_user); free(dest_user); return NULL; } } else { free(key); if (ret == 1) { user_datum_destroy(user); free(user); } } return dest_user; } /* Return a type_datum_t for the local avrule_decl with the given ID. * If it does not exist, create one with the same value as 'value'. * This function assumes that the ID is within scope. c.f., * is_id_in_scope(). * * NOTE: this function usurps ownership of id afterwards. The caller * shall not reference it nor free() it afterwards. */ type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr) { type_datum_t *dest_typdatum; hashtab_t types_tab; assert(stack_top->type == 1); if (stack_top->parent == NULL) { /* in global, so use global symbol table */ types_tab = policydbp->p_types.table; } else { types_tab = stack_top->decl->p_types.table; } dest_typdatum = hashtab_search(types_tab, id); if (!dest_typdatum) { dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); if (dest_typdatum == NULL) { free(id); return NULL; } type_datum_init(dest_typdatum); dest_typdatum->s.value = value; dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE; dest_typdatum->primary = 1; if (hashtab_insert(types_tab, id, dest_typdatum)) { free(id); type_datum_destroy(dest_typdatum); free(dest_typdatum); return NULL; } } else { free(id); if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) { return NULL; } } return dest_typdatum; } /* Return a role_datum_t for the local avrule_decl with the given ID. * If it does not exist, create one with the same value as 'value'. * This function assumes that the ID is within scope. c.f., * is_id_in_scope(). * * NOTE: this function usurps ownership of id afterwards. The caller * shall not reference it nor free() it afterwards. */ role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr) { role_datum_t *dest_roledatum; hashtab_t roles_tab; assert(stack_top->type == 1); if (stack_top->parent == NULL) { /* in global, so use global symbol table */ roles_tab = policydbp->p_roles.table; } else { roles_tab = stack_top->decl->p_roles.table; } dest_roledatum = hashtab_search(roles_tab, id); if (!dest_roledatum) { dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t)); if (dest_roledatum == NULL) { free(id); return NULL; } role_datum_init(dest_roledatum); dest_roledatum->s.value = value; dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; if (hashtab_insert(roles_tab, id, dest_roledatum)) { free(id); role_datum_destroy(dest_roledatum); free(dest_roledatum); return NULL; } } else { free(id); if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE) return NULL; } return dest_roledatum; } /* Attempt to require a symbol within the current scope. If currently * within an optional (and not its else branch), add the symbol to the * required list. Return 0 on success, 1 if caller needs to free() * datum. If symbols may not be declared here return -1. For duplicate * declarations return -2. For all else, including out of memory, * return -3.. Note that dest_value and datum_value might not be * restricted pointers. */ int require_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value) { avrule_decl_t *decl = stack_top->decl; int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_REQ); if (ret < 0) { return ret; } if (ebitmap_set_bit(decl->required.scope + symbol_type, *datum_value - 1, 1)) { return -3; } stack_top->require_given = 1; return ret; } int add_perm_to_class(uint32_t perm_value, uint32_t class_value) { avrule_decl_t *decl = stack_top->decl; scope_index_t *scope; assert(perm_value >= 1); assert(class_value >= 1); scope = &decl->required; if (class_value > scope->class_perms_len) { uint32_t i; ebitmap_t *new_map = realloc(scope->class_perms_map, class_value * sizeof(*new_map)); if (new_map == NULL) { return -1; } scope->class_perms_map = new_map; for (i = scope->class_perms_len; i < class_value; i++) { ebitmap_init(scope->class_perms_map + i); } scope->class_perms_len = class_value; } if (ebitmap_set_bit(scope->class_perms_map + class_value - 1, perm_value - 1, 1)) { return -1; } return 0; } static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); free(datum); return 0; } static void class_datum_destroy(class_datum_t * cladatum) { if (cladatum != NULL) { hashtab_map(cladatum->permissions.table, perm_destroy, NULL); hashtab_destroy(cladatum->permissions.table); free(cladatum); } } int require_class(int pass) { char *class_id = queue_remove(id_queue); char *perm_id = NULL; class_datum_t *datum = NULL; perm_datum_t *perm = NULL; int ret; if (pass == 2) { free(class_id); while ((perm_id = queue_remove(id_queue)) != NULL) free(perm_id); return 0; } /* first add the class if it is not already there */ if (class_id == NULL) { yyerror("no class name for class definition?"); return -1; } if ((datum = calloc(1, sizeof(*datum))) == NULL || symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) { yyerror("Out of memory!"); class_datum_destroy(datum); return -1; } ret = require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value, &datum->s.value); if (ret < 0) { print_error_msg(ret, SYM_CLASSES); free(class_id); class_datum_destroy(datum); return -1; } if (ret == 0) { /* a new class was added; reindex everything */ if (policydb_index_classes(policydbp)) { yyerror("Out of memory!"); return -1; } } else { class_datum_destroy(datum); datum = hashtab_search(policydbp->p_classes.table, class_id); assert(datum); /* the class datum should have existed */ free(class_id); } /* now add each of the permissions to this class's requirements */ while ((perm_id = queue_remove(id_queue)) != NULL) { int allocated = 0; /* Is the permission already in the table? */ perm = hashtab_search(datum->permissions.table, perm_id); if (!perm && datum->comdatum) perm = hashtab_search(datum->comdatum->permissions.table, perm_id); if (perm) { /* Yes, drop the name. */ free(perm_id); } else { /* No - allocate and insert an entry for it. */ if (policydbp->policy_type == POLICY_BASE) { yyerror2 ("Base policy - require of permission %s without prior declaration.", perm_id); free(perm_id); return -1; } allocated = 1; if ((perm = malloc(sizeof(*perm))) == NULL) { yyerror("Out of memory!"); free(perm_id); return -1; } memset(perm, 0, sizeof(*perm)); ret = hashtab_insert(datum->permissions.table, perm_id, perm); if (ret) { yyerror("Out of memory!"); free(perm_id); free(perm); return -1; } perm->s.value = datum->permissions.nprim + 1; } if (add_perm_to_class(perm->s.value, datum->s.value) == -1) { yyerror("Out of memory!"); return -1; } /* Update number of primitives if we allocated one. */ if (allocated) datum->permissions.nprim++; } return 0; } static int require_role_or_attribute(int pass, unsigned char isattr) { char *key = NULL; role_datum_t *role = NULL; int ret; if (pass == 2) { free(queue_remove(id_queue)); return 0; } ret = create_role(SCOPE_REQ, isattr, &role, &key); if (ret < 0) { return -1; } free(key); if (ret == 0) { ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1); if (ret != 0) { yyerror("Out of memory"); return -1; } } else { role_datum_destroy(role); free(role); } return 0; } int require_role(int pass) { return require_role_or_attribute(pass, 0); } int require_attribute_role(int pass) { return require_role_or_attribute(pass, 1); } static int require_type_or_attribute(int pass, unsigned char isattr) { type_datum_t *type = NULL; int ret; if (pass == 2) { free(queue_remove(id_queue)); return 0; } ret = create_type(SCOPE_REQ, isattr, &type); if (ret < 0) { return -1; } return 0; } int require_type(int pass) { return require_type_or_attribute(pass, 0); } int require_attribute(int pass) { return require_type_or_attribute(pass, 1); } int require_user(int pass) { char *key = NULL; user_datum_t *user = NULL; int ret; if (pass == 1) { free(queue_remove(id_queue)); return 0; } ret = create_user(SCOPE_REQ, &user, &key); if (ret < 0) { return -1; } free(key); if (ret == 1) { user_datum_destroy(user); free(user); } return 0; } static int require_bool_tunable(int pass, int is_tunable) { char *id = queue_remove(id_queue); cond_bool_datum_t *booldatum = NULL; int retval; if (pass == 2) { free(id); return 0; } if (id == NULL) { yyerror("no boolean name"); return -1; } if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) { cond_destroy_bool(id, booldatum, NULL); yyerror("Out of memory!"); return -1; } if (is_tunable) booldatum->flags |= COND_BOOL_FLAGS_TUNABLE; retval = require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum, &booldatum->s.value, &booldatum->s.value); if (retval != 0) { cond_destroy_bool(id, booldatum, NULL); if (retval < 0) { print_error_msg(retval, SYM_BOOLS); return -1; } } return 0; } int require_bool(int pass) { return require_bool_tunable(pass, 0); } int require_tunable(int pass) { return require_bool_tunable(pass, 1); } int require_sens(int pass) { char *id = queue_remove(id_queue); level_datum_t *level = NULL; int retval; if (pass == 2) { free(id); return 0; } if (!id) { yyerror("no sensitivity name"); return -1; } level = malloc(sizeof(level_datum_t)); if (!level) { free(id); yyerror("Out of memory!"); return -1; } level_datum_init(level); level->level = malloc(sizeof(mls_level_t)); if (!level->level) { free(id); level_datum_destroy(level); free(level); yyerror("Out of memory!"); return -1; } mls_level_init(level->level); retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, &level->level->sens, &level->level->sens); if (retval != 0) { free(id); mls_level_destroy(level->level); free(level->level); level_datum_destroy(level); free(level); if (retval < 0) { print_error_msg(retval, SYM_LEVELS); return -1; } } return 0; } int require_cat(int pass) { char *id = queue_remove(id_queue); cat_datum_t *cat = NULL; int retval; if (pass == 2) { free(id); return 0; } if (!id) { yyerror("no category name"); return -1; } cat = malloc(sizeof(cat_datum_t)); if (!cat) { free(id); yyerror("Out of memory!"); return -1; } cat_datum_init(cat); retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, &cat->s.value, &cat->s.value); if (retval != 0) { free(id); cat_datum_destroy(cat); free(cat); if (retval < 0) { print_error_msg(retval, SYM_CATS); return -1; } } return 0; } static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) { uint32_t i; if (stack == NULL) { return 0; /* no matching scope found */ } if (stack->type == 1) { avrule_decl_t *decl = stack->decl; for (i = 0; i < scope->decl_ids_len; i++) { if (scope->decl_ids[i] == decl->decl_id) { return 1; } } } else { /* note that conditionals can't declare or require * symbols, so skip this level */ } /* not within scope of this stack, so try its parent */ return is_scope_in_stack(scope, stack->parent); } int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) { scope_datum_t *scope = (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type]. table, id); if (scope == NULL) { return 1; /* id is not known, so return success */ } return is_scope_in_stack(scope, stack_top); } static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, scope_index_t * scope) { if (class_value > scope->class_perms_len) { return 1; } if (ebitmap_get_bit(scope->class_perms_map + class_value - 1, perm_value - 1)) { return 1; } return 0; } static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, scope_stack_t * stack) { if (stack == NULL) { return 0; /* no matching scope found */ } if (stack->type == 1) { avrule_decl_t *decl = stack->decl; if (is_perm_in_scope_index (perm_value, class_value, &decl->required) || is_perm_in_scope_index(perm_value, class_value, &decl->declared)) { return 1; } } else { /* note that conditionals can't declare or require * symbols, so skip this level */ } /* not within scope of this stack, so try its parent */ return is_perm_in_stack(perm_value, class_value, stack->parent); } int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id) { class_datum_t *cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, class_id); perm_datum_t *perdatum; if (cladatum == NULL) { return 1; } perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, perm_id); if (perdatum == NULL) { return 1; } return is_perm_in_stack(perdatum->s.value, cladatum->s.value, stack_top); } cond_list_t *get_current_cond_list(cond_list_t * cond) { /* FIX ME: do something different here if in a nested * conditional? */ avrule_decl_t *decl = stack_top->decl; return get_decl_cond_list(policydbp, decl, cond); } /* Append the new conditional node to the existing ones. During * expansion the list will be reversed -- i.e., the last AV rule will * be the first one listed in the policy. This matches the behavior * of the upstream compiler. */ void append_cond_list(cond_list_t * cond) { cond_list_t *old_cond = get_current_cond_list(cond); avrule_t *tmp; assert(old_cond != NULL); /* probably out of memory */ if (old_cond->avtrue_list == NULL) { old_cond->avtrue_list = cond->avtrue_list; } else { for (tmp = old_cond->avtrue_list; tmp->next != NULL; tmp = tmp->next) ; tmp->next = cond->avtrue_list; } if (old_cond->avfalse_list == NULL) { old_cond->avfalse_list = cond->avfalse_list; } else { for (tmp = old_cond->avfalse_list; tmp->next != NULL; tmp = tmp->next) ; tmp->next = cond->avfalse_list; } old_cond->flags |= cond->flags; } void append_avrule(avrule_t * avrule) { avrule_decl_t *decl = stack_top->decl; /* currently avrules follow a completely different code path * for handling avrules and compute types * (define_cond_avrule_te_avtab, define_cond_compute_type); * therefore there ought never be a conditional on top of the * scope stack */ assert(stack_top->type == 1); if (stack_top->last_avrule == NULL) { decl->avrules = avrule; } else { stack_top->last_avrule->next = avrule; } stack_top->last_avrule = avrule; } /* this doesn't actually append, but really prepends it */ void append_role_trans(role_trans_rule_t * role_tr_rules) { avrule_decl_t *decl = stack_top->decl; /* role transitions are not allowed within conditionals */ assert(stack_top->type == 1); role_tr_rules->next = decl->role_tr_rules; decl->role_tr_rules = role_tr_rules; } /* this doesn't actually append, but really prepends it */ void append_role_allow(role_allow_rule_t * role_allow_rules) { avrule_decl_t *decl = stack_top->decl; /* role allows are not allowed within conditionals */ assert(stack_top->type == 1); role_allow_rules->next = decl->role_allow_rules; decl->role_allow_rules = role_allow_rules; } /* this doesn't actually append, but really prepends it */ void append_filename_trans(filename_trans_rule_t * filename_trans_rules) { avrule_decl_t *decl = stack_top->decl; /* filename transitions are not allowed within conditionals */ assert(stack_top->type == 1); filename_trans_rules->next = decl->filename_trans_rules; decl->filename_trans_rules = filename_trans_rules; } /* this doesn't actually append, but really prepends it */ void append_range_trans(range_trans_rule_t * range_tr_rules) { avrule_decl_t *decl = stack_top->decl; /* range transitions are not allowed within conditionals */ assert(stack_top->type == 1); range_tr_rules->next = decl->range_tr_rules; decl->range_tr_rules = range_tr_rules; } int begin_optional(int pass) { avrule_block_t *block = NULL; avrule_decl_t *decl; if (pass == 1) { /* allocate a new avrule block for this optional block */ if ((block = avrule_block_create()) == NULL || (decl = avrule_decl_create(next_decl_id)) == NULL) { goto cleanup; } block->flags |= AVRULE_OPTIONAL; block->branch_list = decl; last_block->next = block; } else { /* select the next block from the chain built during pass 1 */ block = last_block->next; assert(block != NULL && block->branch_list != NULL && block->branch_list->decl_id == next_decl_id); decl = block->branch_list; } if (push_stack(1, block, decl) == -1) { goto cleanup; } stack_top->last_avrule = NULL; last_block = block; next_decl_id++; return 0; cleanup: yyerror("Out of memory!"); avrule_block_destroy(block); return -1; } int end_optional(int pass __attribute__ ((unused))) { /* once nested conditionals are allowed, do the stack unfolding here */ pop_stack(); return 0; } int begin_optional_else(int pass) { avrule_decl_t *decl; assert(stack_top->type == 1 && stack_top->in_else == 0); if (pass == 1) { /* allocate a new declaration and add it to the * current chain */ if ((decl = avrule_decl_create(next_decl_id)) == NULL) { yyerror("Out of memory!"); return -1; } stack_top->decl->next = decl; } else { /* pick the (hopefully last) declaration of this avrule block, built from pass 1 */ decl = stack_top->decl->next; assert(decl != NULL && decl->next == NULL && decl->decl_id == next_decl_id); } stack_top->in_else = 1; stack_top->decl = decl; stack_top->last_avrule = NULL; stack_top->require_given = 0; next_decl_id++; return 0; } static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack) { uint32_t i; if (stack == NULL) { return 0; } if (stack->type == 1) { scope_index_t *src_scope = &stack->decl->required; scope_index_t *dest_scope = &dest->required; for (i = 0; i < SYM_NUM; i++) { ebitmap_t *src_bitmap = &src_scope->scope[i]; ebitmap_t *dest_bitmap = &dest_scope->scope[i]; if (ebitmap_union(dest_bitmap, src_bitmap)) { yyerror("Out of memory!"); return -1; } } /* now copy class permissions */ if (src_scope->class_perms_len > dest_scope->class_perms_len) { ebitmap_t *new_map = realloc(dest_scope->class_perms_map, src_scope->class_perms_len * sizeof(*new_map)); if (new_map == NULL) { yyerror("Out of memory!"); return -1; } dest_scope->class_perms_map = new_map; for (i = dest_scope->class_perms_len; i < src_scope->class_perms_len; i++) { ebitmap_init(dest_scope->class_perms_map + i); } dest_scope->class_perms_len = src_scope->class_perms_len; } for (i = 0; i < src_scope->class_perms_len; i++) { ebitmap_t *src_bitmap = &src_scope->class_perms_map[i]; ebitmap_t *dest_bitmap = &dest_scope->class_perms_map[i]; if (ebitmap_union(dest_bitmap, src_bitmap)) { yyerror("Out of memory!"); return -1; } } } return copy_requirements(dest, stack->parent); } /* During pass 1, check that at least one thing was required within * this block, for those places where a REQUIRED is necessary. During * pass 2, have this block inherit its parents' requirements. Return * 0 on success, -1 on failure. */ int end_avrule_block(int pass) { avrule_decl_t *decl = stack_top->decl; assert(stack_top->type == 1); if (pass == 2) { /* this avrule_decl inherits all of its parents' * requirements */ if (copy_requirements(decl, stack_top->parent) == -1) { return -1; } return 0; } if (!stack_top->in_else && !stack_top->require_given) { if (policydbp->policy_type == POLICY_BASE && stack_top->parent != NULL) { /* if this is base no require should be in the global block */ return 0; } else { /* non-ELSE branches must have at least one thing required */ yyerror("This block has no require section."); return -1; } } return 0; } /* Push a new scope on to the stack and update the 'last' pointer. * Return 0 on success, -1 if out * of memory. */ static int push_stack(int stack_type, ...) { scope_stack_t *s = calloc(1, sizeof(*s)); va_list ap; if (s == NULL) { return -1; } va_start(ap, stack_type); switch (s->type = stack_type) { case 1:{ s->u.avrule = va_arg(ap, avrule_block_t *); s->decl = va_arg(ap, avrule_decl_t *); break; } case 2:{ s->u.cond_list = va_arg(ap, cond_list_t *); break; } default: /* invalid stack type given */ assert(0); } va_end(ap); s->parent = stack_top; s->child = NULL; stack_top = s; return 0; } /* Pop off the most recently added from the stack. Update the 'last' * pointer. */ static void pop_stack(void) { scope_stack_t *parent; assert(stack_top != NULL); parent = stack_top->parent; if (parent != NULL) { parent->child = NULL; } free(stack_top); stack_top = parent; } checkpolicy/module_compiler.h0100644 0000000 0000000 00000010614 13756670063 015451 0ustar000000000 0000000 /* Author : Joshua Brindle * Karl MacMillan * Jason Tang * Added support for binary policy modules * * Copyright (C) 2004 - 2005 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ #ifndef MODULE_COMPILER_H #define MODULE_COMPILER_H #include /* Called when checkpolicy begins to parse a policy -- either at the * very beginning for a kernel/base policy, or after the module header * for policy modules. Initialize the memory structures within. * Return 0 on success, -1 on error. */ int define_policy(int pass, int module_header_given); /* Declare a symbol declaration to the current avrule_decl. Check * that insertion is allowed here and that the symbol does not already * exist. Returns 0 on success, 1 if symbol was already there (caller * needs to free() the datum), -1 if declarations not allowed, -2 for * duplicate declarations, -3 for all else. */ int declare_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value); role_datum_t *declare_role(unsigned char isattr); type_datum_t *declare_type(unsigned char primary, unsigned char isattr); user_datum_t *declare_user(void); type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr); role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr); /* Add a symbol to the current avrule_block's require section. Note * that a module may not both declare and require the same symbol. * Returns 0 on success, -1 on error. */ int require_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value); /* Enable a permission for a class within the current avrule_decl. * Return 0 on success, -1 if out of memory. */ int add_perm_to_class(uint32_t perm_value, uint32_t class_value); /* Functions called from REQUIRE blocks. Add the first symbol on the * id_queue to this avrule_decl's scope if not already there. * c.f. require_symbol(). */ int require_class(int pass); int require_role(int pass); int require_type(int pass); int require_attribute(int pass); int require_attribute_role(int pass); int require_user(int pass); int require_bool(int pass); int require_tunable(int pass); int require_sens(int pass); int require_cat(int pass); /* Check if an identifier is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id); /* Check if a particular permission is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id); /* Search the current avrules block for a conditional with the same * expression as 'cond'. If the conditional does not exist then * create one. Either way, return the conditional. */ cond_list_t *get_current_cond_list(cond_list_t * cond); /* Append rule to the current avrule_block. */ void append_cond_list(cond_list_t * cond); void append_avrule(avrule_t * avrule); void append_role_trans(role_trans_rule_t * role_tr_rules); void append_role_allow(role_allow_rule_t * role_allow_rules); void append_range_trans(range_trans_rule_t * range_tr_rules); void append_filename_trans(filename_trans_rule_t * filename_trans_rules); /* Create a new optional block and add it to the global policy. * During the second pass resolve the block's requirements. Return 0 * on success, -1 on error. */ int begin_optional(int pass); int end_optional(int pass); /* ELSE blocks are similar to normal blocks with the following two * limitations: * - no declarations are allowed within else branches * - no REQUIRES are allowed; the else branch inherits the parent's * requirements */ int begin_optional_else(int pass); /* Called whenever existing an avrule block. Check that the block had * a non-empty REQUIRE section. If so pop the block off of the scop * stack and return 0. If not then send an error to yyerror and * return -1. */ int end_avrule_block(int pass); #endif checkpolicy/parse_util.c0100644 0000000 0000000 00000004127 13756670063 014436 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "parse_util.h" #include "queue.h" /* these are defined in policy_parse.y and are needed for read_source_policy */ extern FILE *yyin; extern void init_parser(int); extern int yyparse(void); extern void yyrestart(FILE *); extern queue_t id_queue; extern unsigned int policydb_errors; extern unsigned long policydb_lineno; extern policydb_t *policydbp; extern int mlspol; extern void set_source_file(const char *name); int read_source_policy(policydb_t * p, const char *file, const char *progname) { yyin = fopen(file, "r"); if (!yyin) { fprintf(stderr, "%s: unable to open %s\n", progname, file); return -1; } set_source_file(file); if ((id_queue = queue_create()) == NULL) { fprintf(stderr, "%s: out of memory!\n", progname); return -1; } policydbp = p; mlspol = p->mls; init_parser(1); if (yyparse() || policydb_errors) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); return -1; } rewind(yyin); init_parser(2); set_source_file(file); yyrestart(yyin); if (yyparse() || policydb_errors) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); return -1; } queue_destroy(id_queue); if (policydb_errors) return -1; fclose(yyin); return 0; } checkpolicy/parse_util.h0100644 0000000 0000000 00000002525 13756670063 014443 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Utility functions shared by checkpolicy and checkmodule */ #ifndef __PARSE_UTIL_H__ #define __PARSE_UTIL_H__ #include /* Read a source policy and populate the policydb passed in. The * policydb must already have been created and configured (e.g., * expected policy type set. The string progname is used for * error messages. No checking of assertions, hierarchy, etc. * is done. */ int read_source_policy(policydb_t * p, const char *file, const char *progname); #endif checkpolicy/policy_define.c0100644 0000000 0000000 00000352517 13756670063 015111 0ustar000000000 0000000 /* * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: David Caplan, * * Added conditional policy language extensions * * Updated: Joshua Brindle * Karl MacMillan * Jason Tang * * Added support for binary policy modules * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2008 Tresys Technology, LLC * Copyright (C) 2007 Red Hat Inc. * Copyright (C) 2017 Mellanox Techonologies Inc. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* FLASK */ #include #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "queue.h" #include "checkpolicy.h" #include "module_compiler.h" #include "policy_define.h" policydb_t *policydbp; queue_t id_queue = 0; unsigned int pass; char *curfile = 0; int mlspol = 0; extern unsigned long policydb_lineno; extern unsigned long source_lineno; extern unsigned int policydb_errors; extern char source_file[PATH_MAX]; extern int yywarn(const char *msg); extern int yyerror(const char *msg); #define ERRORMSG_LEN 255 static char errormsg[ERRORMSG_LEN + 1] = {0}; static int id_has_dot(char *id); static int parse_security_context(context_struct_t *c); /* initialize all of the state variables for the scanner/parser */ void init_parser(int pass_number) { policydb_lineno = 1; source_lineno = 1; policydb_errors = 0; pass = pass_number; } __attribute__ ((format(printf, 1, 2))) void yyerror2(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf(errormsg, ERRORMSG_LEN, fmt, ap); yyerror(errormsg); va_end(ap); } int insert_separator(int push) { int error; if (push) error = queue_push(id_queue, 0); else error = queue_insert(id_queue, 0); if (error) { yyerror("queue overflow"); return -1; } return 0; } int insert_id(const char *id, int push) { char *newid = 0; int error; newid = (char *)malloc(strlen(id) + 1); if (!newid) { yyerror("out of memory"); return -1; } strcpy(newid, id); if (push) error = queue_push(id_queue, (queue_element_t) newid); else error = queue_insert(id_queue, (queue_element_t) newid); if (error) { yyerror("queue overflow"); free(newid); return -1; } return 0; } /* If the identifier has a dot within it and that its first character is not a dot then return 1, else return 0. */ static int id_has_dot(char *id) { if (strchr(id, '.') >= id + 1) { return 1; } return 0; } int define_class(void) { char *id = 0; class_datum_t *datum = 0; int ret; uint32_t value; if (pass == 2) { id = queue_remove(id_queue); free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no class name for class definition?"); return -1; } datum = (class_datum_t *) malloc(sizeof(class_datum_t)); if (!datum) { yyerror("out of memory"); goto bad; } memset(datum, 0, sizeof(class_datum_t)); ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto bad; } case -2:{ yyerror2("duplicate declaration of class %s", id); goto bad; } case -1:{ yyerror("could not declare class here"); goto bad; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } datum->s.value = value; return 0; bad: if (id) free(id); if (datum) free(datum); return -1; } int define_permissive(void) { char *type = NULL; struct type_datum *t; int rc = 0; type = queue_remove(id_queue); if (!type) { yyerror2("forgot to include type in permissive definition?"); rc = -1; goto out; } if (pass == 1) goto out; if (!is_id_in_scope(SYM_TYPES, type)) { yyerror2("type %s is not within scope", type); rc = -1; goto out; } t = hashtab_search(policydbp->p_types.table, type); if (!t) { yyerror2("type is not defined: %s", type); rc = -1; goto out; } if (t->flavor == TYPE_ATTRIB) { yyerror2("attributes may not be permissive: %s\n", type); rc = -1; goto out; } t->flags |= TYPE_FLAGS_PERMISSIVE; out: free(type); return rc; } int define_polcap(void) { char *id = 0; int capnum; if (pass == 2) { id = queue_remove(id_queue); free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no capability name for policycap definition?"); goto bad; } /* Check for valid cap name -> number mapping */ capnum = sepol_polcap_getnum(id); if (capnum < 0) { yyerror2("invalid policy capability name %s", id); goto bad; } /* Store it */ if (ebitmap_set_bit(&policydbp->policycaps, capnum, TRUE)) { yyerror("out of memory"); goto bad; } free(id); return 0; bad: free(id); return -1; } int define_initial_sid(void) { char *id = 0; ocontext_t *newc = 0, *c, *head; if (pass == 2) { id = queue_remove(id_queue); free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no sid name for SID definition?"); return -1; } newc = (ocontext_t *) malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); goto bad; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = id; context_init(&newc->context[0]); head = policydbp->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { if (!strcmp(newc->u.name, c->u.name)) { yyerror2("duplicate initial SID %s", id); goto bad; } } if (head) { newc->sid[0] = head->sid[0] + 1; } else { newc->sid[0] = 1; } newc->next = head; policydbp->ocontexts[OCON_ISID] = newc; return 0; bad: if (id) free(id); if (newc) free(newc); return -1; } static int read_classes(ebitmap_t *e_classes) { char *id; class_datum_t *cladatum; while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); free(id); return -1; } free(id); if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) { yyerror("Out of memory"); return -1; } } return 0; } int define_default_user(int which) { char *id; class_datum_t *cladatum; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); return -1; } if (cladatum->default_user && cladatum->default_user != which) { yyerror2("conflicting default user information for class %s", id); return -1; } cladatum->default_user = which; free(id); } return 0; } int define_default_role(int which) { char *id; class_datum_t *cladatum; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); return -1; } if (cladatum->default_role && cladatum->default_role != which) { yyerror2("conflicting default role information for class %s", id); return -1; } cladatum->default_role = which; free(id); } return 0; } int define_default_type(int which) { char *id; class_datum_t *cladatum; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); return -1; } if (cladatum->default_type && cladatum->default_type != which) { yyerror2("conflicting default type information for class %s", id); return -1; } cladatum->default_type = which; free(id); } return 0; } int define_default_range(int which) { char *id; class_datum_t *cladatum; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); return -1; } if (cladatum->default_range && cladatum->default_range != which) { yyerror2("conflicting default range information for class %s", id); return -1; } cladatum->default_range = which; free(id); } return 0; } int define_common_perms(void) { char *id = 0, *perm = 0; common_datum_t *comdatum = 0; perm_datum_t *perdatum = 0; int ret; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no common name for common perm definition?"); return -1; } comdatum = hashtab_search(policydbp->p_commons.table, id); if (comdatum) { yyerror2("duplicate declaration for common %s\n", id); return -1; } comdatum = (common_datum_t *) malloc(sizeof(common_datum_t)); if (!comdatum) { yyerror("out of memory"); goto bad; } memset(comdatum, 0, sizeof(common_datum_t)); ret = hashtab_insert(policydbp->p_commons.table, (hashtab_key_t) id, (hashtab_datum_t) comdatum); if (ret == SEPOL_EEXIST) { yyerror("duplicate common definition"); goto bad; } if (ret == SEPOL_ENOMEM) { yyerror("hash table overflow"); goto bad; } comdatum->s.value = policydbp->p_commons.nprim + 1; if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) { yyerror("out of memory"); goto bad; } policydbp->p_commons.nprim++; while ((perm = queue_remove(id_queue))) { perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t)); if (!perdatum) { yyerror("out of memory"); goto bad_perm; } memset(perdatum, 0, sizeof(perm_datum_t)); perdatum->s.value = comdatum->permissions.nprim + 1; if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) { yyerror ("too many permissions to fit in an access vector"); goto bad_perm; } ret = hashtab_insert(comdatum->permissions.table, (hashtab_key_t) perm, (hashtab_datum_t) perdatum); if (ret == SEPOL_EEXIST) { yyerror2("duplicate permission %s in common %s", perm, id); goto bad_perm; } if (ret == SEPOL_ENOMEM) { yyerror("hash table overflow"); goto bad_perm; } comdatum->permissions.nprim++; } return 0; bad: if (id) free(id); if (comdatum) free(comdatum); return -1; bad_perm: if (perm) free(perm); if (perdatum) free(perdatum); return -1; } int define_av_perms(int inherits) { char *id; class_datum_t *cladatum; common_datum_t *comdatum; perm_datum_t *perdatum = 0, *perdatum2 = 0; int ret; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no tclass name for av perm definition?"); return -1; } cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, (hashtab_key_t) id); if (!cladatum) { yyerror2("class %s is not defined", id); goto bad; } free(id); if (cladatum->comdatum || cladatum->permissions.nprim) { yyerror("duplicate access vector definition"); return -1; } if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) { yyerror("out of memory"); return -1; } if (inherits) { id = (char *)queue_remove(id_queue); if (!id) { yyerror ("no inherits name for access vector definition?"); return -1; } comdatum = (common_datum_t *) hashtab_search(policydbp->p_commons. table, (hashtab_key_t) id); if (!comdatum) { yyerror2("common %s is not defined", id); goto bad; } cladatum->comkey = id; cladatum->comdatum = comdatum; /* * Class-specific permissions start with values * after the last common permission. */ cladatum->permissions.nprim += comdatum->permissions.nprim; } while ((id = queue_remove(id_queue))) { perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t)); if (!perdatum) { yyerror("out of memory"); goto bad; } memset(perdatum, 0, sizeof(perm_datum_t)); perdatum->s.value = ++cladatum->permissions.nprim; if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) { yyerror ("too many permissions to fit in an access vector"); goto bad; } if (inherits) { /* * Class-specific permissions and * common permissions exist in the same * name space. */ perdatum2 = (perm_datum_t *) hashtab_search(cladatum->comdatum-> permissions.table, (hashtab_key_t) id); if (perdatum2) { yyerror2("permission %s conflicts with an " "inherited permission", id); goto bad; } } ret = hashtab_insert(cladatum->permissions.table, (hashtab_key_t) id, (hashtab_datum_t) perdatum); if (ret == SEPOL_EEXIST) { yyerror2("duplicate permission %s", id); goto bad; } if (ret == SEPOL_ENOMEM) { yyerror("hash table overflow"); goto bad; } if (add_perm_to_class(perdatum->s.value, cladatum->s.value)) { yyerror("out of memory"); goto bad; } } return 0; bad: if (id) free(id); if (perdatum) free(perdatum); return -1; } int define_sens(void) { char *id; mls_level_t *level = 0; level_datum_t *datum = 0, *aliasdatum = 0; int ret; uint32_t value; /* dummy variable -- its value is never used */ if (!mlspol) { yyerror("sensitivity definition in non-MLS configuration"); return -1; } if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no sensitivity name for sensitivity definition?"); return -1; } if (id_has_dot(id)) { yyerror("sensitivity identifiers may not contain periods"); goto bad; } level = (mls_level_t *) malloc(sizeof(mls_level_t)); if (!level) { yyerror("out of memory"); goto bad; } mls_level_init(level); level->sens = 0; /* actual value set in define_dominance */ ebitmap_init(&level->cat); /* actual value set in define_level */ datum = (level_datum_t *) malloc(sizeof(level_datum_t)); if (!datum) { yyerror("out of memory"); goto bad; } level_datum_init(datum); datum->isalias = FALSE; datum->level = level; ret = declare_symbol(SYM_LEVELS, id, datum, &value, &value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto bad; } case -2:{ yyerror("duplicate declaration of sensitivity level"); goto bad; } case -1:{ yyerror("could not declare sensitivity level here"); goto bad; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { yyerror("sensitivity aliases may not contain periods"); goto bad_alias; } aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t)); if (!aliasdatum) { yyerror("out of memory"); goto bad_alias; } level_datum_init(aliasdatum); aliasdatum->isalias = TRUE; aliasdatum->level = level; ret = declare_symbol(SYM_LEVELS, id, aliasdatum, NULL, &value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto bad_alias; } case -2:{ yyerror ("duplicate declaration of sensitivity alias"); goto bad_alias; } case -1:{ yyerror ("could not declare sensitivity alias here"); goto bad_alias; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } } return 0; bad: if (id) free(id); if (level) free(level); if (datum) { level_datum_destroy(datum); free(datum); } return -1; bad_alias: if (id) free(id); if (aliasdatum) { level_datum_destroy(aliasdatum); free(aliasdatum); } return -1; } int define_dominance(void) { level_datum_t *datum; uint32_t order; char *id; if (!mlspol) { yyerror("dominance definition in non-MLS configuration"); return -1; } if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } order = 0; while ((id = (char *)queue_remove(id_queue))) { datum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, (hashtab_key_t) id); if (!datum) { yyerror2("unknown sensitivity %s used in dominance " "definition", id); free(id); return -1; } if (datum->level->sens != 0) { yyerror2("sensitivity %s occurs multiply in dominance " "definition", id); free(id); return -1; } datum->level->sens = ++order; /* no need to keep sensitivity name */ free(id); } if (order != policydbp->p_levels.nprim) { yyerror ("all sensitivities must be specified in dominance definition"); return -1; } return 0; } int define_category(void) { char *id; cat_datum_t *datum = 0, *aliasdatum = 0; int ret; uint32_t value; if (!mlspol) { yyerror("category definition in non-MLS configuration"); return -1; } if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no category name for category definition?"); return -1; } if (id_has_dot(id)) { yyerror("category identifiers may not contain periods"); goto bad; } datum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); if (!datum) { yyerror("out of memory"); goto bad; } cat_datum_init(datum); datum->isalias = FALSE; ret = declare_symbol(SYM_CATS, id, datum, &value, &value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto bad; } case -2:{ yyerror("duplicate declaration of category"); goto bad; } case -1:{ yyerror("could not declare category here"); goto bad; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } datum->s.value = value; while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { yyerror("category aliases may not contain periods"); goto bad_alias; } aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); if (!aliasdatum) { yyerror("out of memory"); goto bad_alias; } cat_datum_init(aliasdatum); aliasdatum->isalias = TRUE; aliasdatum->s.value = datum->s.value; ret = declare_symbol(SYM_CATS, id, aliasdatum, NULL, &datum->s.value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto bad_alias; } case -2:{ yyerror ("duplicate declaration of category aliases"); goto bad_alias; } case -1:{ yyerror ("could not declare category aliases here"); goto bad_alias; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } } return 0; bad: if (id) free(id); if (datum) { cat_datum_destroy(datum); free(datum); } return -1; bad_alias: if (id) free(id); if (aliasdatum) { cat_datum_destroy(aliasdatum); free(aliasdatum); } return -1; } static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { level_datum_t *levdatum = (level_datum_t *) datum; mls_level_t *level = (mls_level_t *) arg, *newlevel; if (levdatum->level == level) { levdatum->defined = 1; if (!levdatum->isalias) return 0; newlevel = (mls_level_t *) malloc(sizeof(mls_level_t)); if (!newlevel) return -1; if (mls_level_cpy(newlevel, level)) { free(newlevel); return -1; } levdatum->level = newlevel; } return 0; } int define_level(void) { char *id; level_datum_t *levdatum; if (!mlspol) { yyerror("level definition in non-MLS configuration"); return -1; } if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no level name for level definition?"); return -1; } levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, (hashtab_key_t) id); if (!levdatum) { yyerror2("unknown sensitivity %s used in level definition", id); free(id); return -1; } if (ebitmap_length(&levdatum->level->cat)) { yyerror2("sensitivity %s used in multiple level definitions", id); free(id); return -1; } free(id); levdatum->defined = 1; while ((id = queue_remove(id_queue))) { cat_datum_t *cdatum; int range_start, range_end, i; if (id_has_dot(id)) { char *id_start = id; char *id_end = strchr(id, '.'); *(id_end++) = '\0'; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats. table, (hashtab_key_t) id_start); if (!cdatum) { yyerror2("unknown category %s", id_start); free(id); return -1; } range_start = cdatum->s.value - 1; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats. table, (hashtab_key_t) id_end); if (!cdatum) { yyerror2("unknown category %s", id_end); free(id); return -1; } range_end = cdatum->s.value - 1; if (range_end < range_start) { yyerror2("category range is invalid"); free(id); return -1; } } else { cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats. table, (hashtab_key_t) id); if (!cdatum) { yyerror2("unknown category %s", id); free(id); return -1; } range_start = range_end = cdatum->s.value - 1; } for (i = range_start; i <= range_end; i++) { if (ebitmap_set_bit(&levdatum->level->cat, i, TRUE)) { yyerror("out of memory"); free(id); return -1; } } free(id); } if (hashtab_map (policydbp->p_levels.table, clone_level, levdatum->level)) { yyerror("out of memory"); return -1; } return 0; } int define_attrib(void) { if (pass == 2) { free(queue_remove(id_queue)); return 0; } if (declare_type(TRUE, TRUE) == NULL) { return -1; } return 0; } int expand_attrib(void) { char *id; ebitmap_t attrs; type_datum_t *attr; ebitmap_node_t *node; uint32_t i; int rc = -1; int flags = 0; if (pass == 1) { for (i = 0; i < 2; i++) { while ((id = queue_remove(id_queue))) { free(id); } } return 0; } ebitmap_init(&attrs); while ((id = queue_remove(id_queue))) { if (!id) { yyerror("No attribute name for expandattribute statement?"); goto exit; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("attribute %s is not within scope", id); goto exit; } attr = hashtab_search(policydbp->p_types.table, id); if (!attr) { yyerror2("attribute %s is not declared", id); goto exit; } if (attr->flavor != TYPE_ATTRIB) { yyerror2("%s is a type, not an attribute", id); goto exit; } if (ebitmap_set_bit(&attrs, attr->s.value - 1, TRUE)) { yyerror("Out of memory!"); goto exit; } free(id); } id = (char *) queue_remove(id_queue); if (!id) { yyerror("No option specified for attribute expansion."); goto exit; } if (!strcmp(id, "T")) { flags = TYPE_FLAGS_EXPAND_ATTR_TRUE; } else { flags = TYPE_FLAGS_EXPAND_ATTR_FALSE; } ebitmap_for_each_bit(&attrs, node, i) { if (!ebitmap_node_get_bit(node, i)){ continue; } attr = hashtab_search(policydbp->p_types.table, policydbp->sym_val_to_name[SYM_TYPES][i]); attr->flags |= flags; if ((attr->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) && (attr->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE)) { yywarn("Expandattribute option was set to both true and false. " "Resolving to false."); attr->flags &= ~TYPE_FLAGS_EXPAND_ATTR_TRUE; } } rc = 0; exit: ebitmap_destroy(&attrs); free(id); return rc; } static int add_aliases_to_type(type_datum_t * type) { char *id; type_datum_t *aliasdatum = NULL; int ret; while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { free(id); yyerror ("type alias identifiers may not contain periods"); return -1; } aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); if (!aliasdatum) { free(id); yyerror("Out of memory!"); return -1; } memset(aliasdatum, 0, sizeof(type_datum_t)); aliasdatum->s.value = type->s.value; ret = declare_symbol(SYM_TYPES, id, aliasdatum, NULL, &aliasdatum->s.value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto cleanup; } case -2:{ yyerror2("duplicate declaration of alias %s", id); goto cleanup; } case -1:{ yyerror("could not declare alias here"); goto cleanup; } case 0: break; case 1:{ /* ret == 1 means the alias was required and therefore already * has a value. Set it up as an alias with a different primary. */ type_datum_destroy(aliasdatum); free(aliasdatum); aliasdatum = hashtab_search(policydbp->symtab[SYM_TYPES].table, id); assert(aliasdatum); aliasdatum->primary = type->s.value; aliasdatum->flavor = TYPE_ALIAS; break; } default:{ assert(0); /* should never get here */ } } } return 0; cleanup: free(id); type_datum_destroy(aliasdatum); free(aliasdatum); return -1; } int define_typealias(void) { char *id; type_datum_t *t; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no type name for typealias definition?"); return -1; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); return -1; } t = hashtab_search(policydbp->p_types.table, id); if (!t || t->flavor == TYPE_ATTRIB) { yyerror2("unknown type %s, or it was already declared as an " "attribute", id); free(id); return -1; } free(id); return add_aliases_to_type(t); } int define_typeattribute(void) { char *id; type_datum_t *t, *attr; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no type name for typeattribute definition?"); return -1; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); return -1; } t = hashtab_search(policydbp->p_types.table, id); if (!t || t->flavor == TYPE_ATTRIB) { yyerror2("unknown type %s", id); free(id); return -1; } free(id); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("attribute %s is not within scope", id); free(id); return -1; } attr = hashtab_search(policydbp->p_types.table, id); if (!attr) { /* treat it as a fatal error */ yyerror2("attribute %s is not declared", id); free(id); return -1; } if (attr->flavor != TYPE_ATTRIB) { yyerror2("%s is a type, not an attribute", id); free(id); return -1; } if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) { yyerror("Out of memory!"); return -1; } if (ebitmap_set_bit(&attr->types, (t->s.value - 1), TRUE)) { yyerror("out of memory"); return -1; } } return 0; } static int define_typebounds_helper(char *bounds_id, char *type_id) { type_datum_t *bounds, *type; if (!is_id_in_scope(SYM_TYPES, bounds_id)) { yyerror2("type %s is not within scope", bounds_id); return -1; } bounds = hashtab_search(policydbp->p_types.table, bounds_id); if (!bounds || bounds->flavor == TYPE_ATTRIB) { yyerror2("hoge unknown type %s", bounds_id); return -1; } if (!is_id_in_scope(SYM_TYPES, type_id)) { yyerror2("type %s is not within scope", type_id); return -1; } type = hashtab_search(policydbp->p_types.table, type_id); if (!type || type->flavor == TYPE_ATTRIB) { yyerror2("type %s is not declared", type_id); return -1; } if (type->flavor == TYPE_TYPE && !type->primary) { type = policydbp->type_val_to_struct[type->s.value - 1]; } else if (type->flavor == TYPE_ALIAS) { type = policydbp->type_val_to_struct[type->primary - 1]; } if (!type->bounds) type->bounds = bounds->s.value; else if (type->bounds != bounds->s.value) { yyerror2("type %s has inconsistent master {%s,%s}", type_id, policydbp->p_type_val_to_name[type->bounds - 1], policydbp->p_type_val_to_name[bounds->s.value - 1]); return -1; } return 0; } int define_typebounds(void) { char *bounds, *id; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } bounds = (char *) queue_remove(id_queue); if (!bounds) { yyerror("no type name for typebounds definition?"); return -1; } while ((id = queue_remove(id_queue))) { if (define_typebounds_helper(bounds, id)) return -1; free(id); } free(bounds); return 0; } int define_type(int alias) { char *id; type_datum_t *datum, *attr; if (pass == 2) { /* * If type name contains ".", we have to define boundary * relationship implicitly to keep compatibility with * old name based hierarchy. */ if ((id = queue_remove(id_queue))) { char *bounds, *delim; if ((delim = strrchr(id, '.')) && (bounds = strdup(id))) { bounds[(size_t)(delim - id)] = '\0'; if (define_typebounds_helper(bounds, id)) return -1; free(bounds); } free(id); } if (alias) { while ((id = queue_remove(id_queue))) free(id); } while ((id = queue_remove(id_queue))) free(id); return 0; } if ((datum = declare_type(TRUE, FALSE)) == NULL) { return -1; } if (alias) { if (add_aliases_to_type(datum) == -1) { return -1; } } while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("attribute %s is not within scope", id); free(id); return -1; } attr = hashtab_search(policydbp->p_types.table, id); if (!attr) { /* treat it as a fatal error */ yyerror2("attribute %s is not declared", id); free(id); return -1; } if (attr->flavor != TYPE_ATTRIB) { yyerror2("%s is a type, not an attribute", id); free(id); return -1; } if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) { yyerror("Out of memory!"); return -1; } if (ebitmap_set_bit(&attr->types, datum->s.value - 1, TRUE)) { yyerror("Out of memory"); return -1; } } return 0; } struct val_to_name { unsigned int val; char *name; }; /* Adds a type, given by its textual name, to a typeset. If *add is 0, then add the type to the negative set; otherwise if *add is 1 then add it to the positive side. */ static int set_types(type_set_t * set, char *id, int *add, char starallowed) { type_datum_t *t; if (strcmp(id, "*") == 0) { free(id); if (!starallowed) { yyerror("* not allowed in this type of rule"); return -1; } /* set TYPE_STAR flag */ set->flags = TYPE_STAR; *add = 1; return 0; } if (strcmp(id, "~") == 0) { free(id); if (!starallowed) { yyerror("~ not allowed in this type of rule"); return -1; } /* complement the set */ set->flags = TYPE_COMP; *add = 1; return 0; } if (strcmp(id, "-") == 0) { *add = 0; free(id); return 0; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); return -1; } t = hashtab_search(policydbp->p_types.table, id); if (!t) { yyerror2("unknown type %s", id); free(id); return -1; } if (*add == 0) { if (ebitmap_set_bit(&set->negset, t->s.value - 1, TRUE)) goto oom; } else { if (ebitmap_set_bit(&set->types, t->s.value - 1, TRUE)) goto oom; } free(id); *add = 1; return 0; oom: yyerror("Out of memory"); free(id); return -1; } int define_compute_type_helper(int which, avrule_t ** rule) { char *id; type_datum_t *datum; ebitmap_t tclasses; ebitmap_node_t *node; avrule_t *avrule; class_perm_node_t *perm; uint32_t i; int add = 1; avrule = malloc(sizeof(avrule_t)); if (!avrule) { yyerror("out of memory"); return -1; } avrule_init(avrule); avrule->specified = which; avrule->line = policydb_lineno; avrule->source_line = source_lineno; avrule->source_filename = strdup(source_file); if (!avrule->source_filename) { yyerror("out of memory"); return -1; } while ((id = queue_remove(id_queue))) { if (set_types(&avrule->stypes, id, &add, 0)) goto bad; } add = 1; while ((id = queue_remove(id_queue))) { if (set_types(&avrule->ttypes, id, &add, 0)) goto bad; } ebitmap_init(&tclasses); if (read_classes(&tclasses)) goto bad; id = (char *)queue_remove(id_queue); if (!id) { yyerror("no newtype?"); goto bad; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); goto bad; } datum = (type_datum_t *) hashtab_search(policydbp->p_types.table, (hashtab_key_t) id); if (!datum || datum->flavor == TYPE_ATTRIB) { yyerror2("unknown type %s", id); free(id); goto bad; } free(id); ebitmap_for_each_bit(&tclasses, node, i) { if (ebitmap_node_get_bit(node, i)) { perm = malloc(sizeof(class_perm_node_t)); if (!perm) { yyerror("out of memory"); goto bad; } class_perm_node_init(perm); perm->tclass = i + 1; perm->data = datum->s.value; perm->next = avrule->perms; avrule->perms = perm; } } ebitmap_destroy(&tclasses); *rule = avrule; return 0; bad: avrule_destroy(avrule); free(avrule); return -1; } int define_compute_type(int which) { char *id; avrule_t *avrule; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); id = queue_remove(id_queue); free(id); return 0; } if (define_compute_type_helper(which, &avrule)) return -1; append_avrule(avrule); return 0; } avrule_t *define_cond_compute_type(int which) { char *id; avrule_t *avrule; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); id = queue_remove(id_queue); free(id); return (avrule_t *) 1; } if (define_compute_type_helper(which, &avrule)) return COND_ERR; return avrule; } int define_bool_tunable(int is_tunable) { char *id, *bool_value; cond_bool_datum_t *datum; int ret; uint32_t value; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no identifier for bool definition?"); return -1; } if (id_has_dot(id)) { free(id); yyerror("boolean identifiers may not contain periods"); return -1; } datum = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t)); if (!datum) { yyerror("out of memory"); free(id); return -1; } memset(datum, 0, sizeof(cond_bool_datum_t)); if (is_tunable) datum->flags |= COND_BOOL_FLAGS_TUNABLE; ret = declare_symbol(SYM_BOOLS, id, datum, &value, &value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto cleanup; } case -2:{ yyerror2("duplicate declaration of boolean %s", id); goto cleanup; } case -1:{ yyerror("could not declare boolean here"); goto cleanup; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } datum->s.value = value; bool_value = (char *)queue_remove(id_queue); if (!bool_value) { yyerror("no default value for bool definition?"); return -1; } datum->state = (int)(bool_value[0] == 'T') ? 1 : 0; free(bool_value); return 0; cleanup: cond_destroy_bool(id, datum, NULL); return -1; } avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl) { if (pass == 1) { /* return something so we get through pass 1 */ return (avrule_t *) 1; } if (sl == NULL) { /* This is a require block, return previous list */ return avlist; } /* prepend the new avlist to the pre-existing one */ sl->next = avlist; return sl; } typedef struct av_ioctl_range { uint16_t low; uint16_t high; } av_ioctl_range_t; struct av_ioctl_range_list { uint8_t omit; av_ioctl_range_t range; struct av_ioctl_range_list *next; }; int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL; /* order list by range.low */ for (r = *rangehead; r != NULL; r = r->next) { sorted = malloc(sizeof(struct av_ioctl_range_list)); if (sorted == NULL) goto error; memcpy(sorted, r, sizeof(struct av_ioctl_range_list)); sorted->next = NULL; if (sortedhead == NULL) { sortedhead = sorted; continue; } for (r2 = sortedhead; r2 != NULL; r2 = r2->next) { if (sorted->range.low < r2->range.low) { /* range is the new head */ sorted->next = r2; sortedhead = sorted; break; } else if ((r2 ->next != NULL) && (r->range.low < r2->next->range.low)) { /* insert range between elements */ sorted->next = r2->next; r2->next = sorted; break; } else if (r2->next == NULL) { /* range is the new tail*/ r2->next = sorted; break; } } } r = *rangehead; while (r != NULL) { r2 = r; r = r->next; free(r2); } *rangehead = sortedhead; return 0; error: yyerror("out of memory"); return -1; } int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *r, *tmp; r = *rangehead; while (r != NULL && r->next != NULL) { /* merge */ if ((r->range.high + 1) >= r->next->range.low) { /* keep the higher of the two */ if (r->range.high < r->next->range.high) r->range.high = r->next->range.high; tmp = r->next; r->next = r->next->next; free(tmp); continue; } r = r->next; } return 0; } int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) { char *id; struct av_ioctl_range_list *rnew, *r = NULL; *rangehead = NULL; uint8_t omit = 0; /* read in all the ioctl commands */ while ((id = queue_remove(id_queue))) { if (strcmp(id,"~") == 0) { /* these are values to be omitted */ free(id); omit = 1; } else if (strcmp(id,"-") == 0) { /* high value of range */ free(id); id = queue_remove(id_queue); r->range.high = (uint16_t) strtoul(id,NULL,0); if (r->range.high < r->range.low) { yyerror("Ioctl ranges must be in ascending order."); return -1; } free(id); } else { /* read in new low value */ rnew = malloc(sizeof(struct av_ioctl_range_list)); if (rnew == NULL) goto error; rnew->next = NULL; if (*rangehead == NULL) { *rangehead = rnew; r = *rangehead; } else { r->next = rnew; r = r->next; } rnew->range.low = (uint16_t) strtoul(id,NULL,0); rnew->range.high = rnew->range.low; free(id); } } r = *rangehead; r->omit = omit; return 0; error: yyerror("out of memory"); return -1; } /* flip to included ranges */ int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *rnew, *r, *newhead, *r2; rnew = calloc(1, sizeof(struct av_ioctl_range_list)); if (!rnew) goto error; newhead = rnew; r = *rangehead; r2 = newhead; if (r->range.low == 0) { r2->range.low = r->range.high + 1; r = r->next; } else { r2->range.low = 0; } while (r) { r2->range.high = r->range.low - 1; rnew = calloc(1, sizeof(struct av_ioctl_range_list)); if (!rnew) goto error; r2->next = rnew; r2 = r2->next; r2->range.low = r->range.high + 1; if (!r->next) r2->range.high = 0xffff; r = r->next; } r = *rangehead; while (r != NULL) { r2 = r; r = r->next; free(r2); } *rangehead = newhead; return 0; error: yyerror("out of memory"); return -1; } int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) { struct av_ioctl_range_list *rangehead; uint8_t omit; /* read in ranges to include and omit */ if (avrule_read_ioctls(&rangehead)) return -1; if (rangehead == NULL) { yyerror("error processing ioctl commands"); return -1; } omit = rangehead->omit; /* sort and merge the input ioctls */ if (avrule_sort_ioctls(&rangehead)) return -1; if (avrule_merge_ioctls(&rangehead)) return -1; /* flip ranges if these are ommited*/ if (omit) { if (avrule_omit_ioctls(&rangehead)) return -1; } *rangelist = rangehead; return 0; } int define_te_avtab_xperms_helper(int which, avrule_t ** rule) { char *id; class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL; class_datum_t *cladatum; perm_datum_t *perdatum = NULL; ebitmap_t tclasses; ebitmap_node_t *node; avrule_t *avrule; unsigned int i; int add = 1, ret = 0; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) { yyerror("out of memory"); ret = -1; goto out; } avrule_init(avrule); avrule->specified = which; avrule->line = policydb_lineno; avrule->source_line = source_lineno; avrule->source_filename = strdup(source_file); avrule->xperms = NULL; if (!avrule->source_filename) { yyerror("out of memory"); return -1; } while ((id = queue_remove(id_queue))) { if (set_types (&avrule->stypes, id, &add, which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } } add = 1; while ((id = queue_remove(id_queue))) { if (strcmp(id, "self") == 0) { free(id); if (add == 0) { yyerror("-self is not supported"); ret = -1; goto out; } avrule->flags |= RULE_SELF; continue; } if (set_types (&avrule->ttypes, id, &add, which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } } ebitmap_init(&tclasses); ret = read_classes(&tclasses); if (ret) goto out; perms = NULL; id = queue_head(id_queue); ebitmap_for_each_bit(&tclasses, node, i) { if (!ebitmap_node_get_bit(node, i)) continue; cur_perms = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!cur_perms) { yyerror("out of memory"); ret = -1; goto out; } class_perm_node_init(cur_perms); cur_perms->tclass = i + 1; if (!perms) perms = cur_perms; if (tail) tail->next = cur_perms; tail = cur_perms; cladatum = policydbp->class_val_to_struct[i]; perdatum = hashtab_search(cladatum->permissions.table, id); if (!perdatum) { if (cladatum->comdatum) { perdatum = hashtab_search(cladatum->comdatum-> permissions.table, id); } } if (!perdatum) { yyerror2("permission %s is not defined" " for class %s", id, policydbp->p_class_val_to_name[i]); continue; } else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) { yyerror2("permission %s of class %s is" " not within scope", id, policydbp->p_class_val_to_name[i]); continue; } else { cur_perms->data |= 1U << (perdatum->s.value - 1); } } ebitmap_destroy(&tclasses); avrule->perms = perms; *rule = avrule; out: return ret; } /* index of the u32 containing the permission */ #define XPERM_IDX(x) (x >> 5) /* set bits 0 through x-1 within the u32 */ #define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1) /* low value for this u32 */ #define XPERM_LOW(x) (x << 5) /* high value for this u32 */ #define XPERM_HIGH(x) (((x + 1) << 5) - 1) void avrule_xperm_setrangebits(uint16_t low, uint16_t high, av_extended_perms_t *xperms) { unsigned int i; uint16_t h = high + 1; /* for each u32 that this low-high range touches, set driver permissions */ for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) { /* set all bits in u32 */ if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U; /* set low bits */ else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h); /* set high bits */ else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U - XPERM_SETBITS(low); /* set middle bits */ else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low); } } int avrule_xperms_used(av_extended_perms_t *xperms) { unsigned int i; for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) { if (xperms->perms[i]) return 1; } return 0; } /* * using definitions found in kernel document ioctl-number.txt * The kernel components of an ioctl command are: * dir, size, driver, and fucntion. Only the driver and function fields * are considered here */ #define IOC_DRIV(x) (x >> 8) #define IOC_FUNC(x) (x & 0xff) #define IOC_CMD(driver, func) ((driver << 8) + func) int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, av_extended_perms_t *complete_driver, av_extended_perms_t **extended_perms) { struct av_ioctl_range_list *r; av_extended_perms_t *xperms; uint8_t low, high; xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); return - 1; } r = rangelist; while(r) { low = IOC_DRIV(r->range.low); high = IOC_DRIV(r->range.high); if (complete_driver) { if (!xperm_test(low, complete_driver->perms)) xperm_set(low, xperms->perms); if (!xperm_test(high, complete_driver->perms)) xperm_set(high, xperms->perms); } else { xperm_set(low, xperms->perms); xperm_set(high, xperms->perms); } r = r->next; } if (avrule_xperms_used(xperms)) { *extended_perms = xperms; } else { free(xperms); *extended_perms = NULL; } return 0; } int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, av_extended_perms_t **extended_perms) { struct av_ioctl_range_list *r; av_extended_perms_t *xperms; uint16_t low, high; xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); return - 1; } r = rangelist; while(r) { /* * Any driver code that has sequence 0x00 - 0xff is a complete code, * * if command number = 0xff, then round high up to next code, * else 0x00 - 0xfe keep current code * of this range. temporarily u32 for the + 1 * to account for possible rollover before right shift */ high = IOC_DRIV((uint32_t) (r->range.high + 1)); /* if 0x00 keep current driver code else 0x01 - 0xff round up to next code*/ low = IOC_DRIV(r->range.low); if (IOC_FUNC(r->range.low)) low++; if (high > low) avrule_xperm_setrangebits(low, high - 1, xperms); r = r->next; } if (avrule_xperms_used(xperms)) { xperms->driver = 0x00; xperms->specified = AVRULE_XPERMS_IOCTLDRIVER; *extended_perms = xperms; } else { free(xperms); *extended_perms = NULL; } return 0; } int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, av_extended_perms_t **extended_perms, unsigned int driver) { struct av_ioctl_range_list *r; av_extended_perms_t *xperms; uint16_t low, high; *extended_perms = NULL; xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); return - 1; } r = rangelist; /* for the passed in driver code, find the ranges that apply */ while (r) { low = r->range.low; high = r->range.high; if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) { r = r->next; continue; } if (driver == IOC_DRIV(low)) { if (high > IOC_CMD(driver, 0xff)) high = IOC_CMD(driver, 0xff); } else { if (low < IOC_CMD(driver, 0)) low = IOC_CMD(driver, 0); } low = IOC_FUNC(low); high = IOC_FUNC(high); avrule_xperm_setrangebits(low, high, xperms); xperms->driver = driver; xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION; r = r->next; } if (avrule_xperms_used(xperms)) { *extended_perms = xperms; } else { free(xperms); *extended_perms = NULL; } return 0; } void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist) { struct av_ioctl_range_list *r, *tmp; r = rangelist; while (r) { tmp = r; r = r->next; free(tmp); } } unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms) { unsigned int i; for (i = *bit; i < sizeof(xperms->perms)*8; i++) { if (xperm_test(i,xperms->perms)) { xperm_clear(i, xperms->perms); *bit = i; return 1; } } return 0; } int avrule_cpy(avrule_t *dest, avrule_t *src) { class_perm_node_t *src_perms; class_perm_node_t *dest_perms, *dest_tail; dest_tail = NULL; avrule_init(dest); dest->specified = src->specified; dest->flags = src->flags; if (type_set_cpy(&dest->stypes, &src->stypes)) { yyerror("out of memory"); return - 1; } if (type_set_cpy(&dest->ttypes, &src->ttypes)) { yyerror("out of memory"); return - 1; } dest->line = src->line; dest->source_filename = strdup(source_file); if (!dest->source_filename) { yyerror("out of memory"); return -1; } dest->source_line = src->source_line; /* increment through the class perms and copy over */ src_perms = src->perms; while (src_perms) { dest_perms = (class_perm_node_t *) calloc(1, sizeof(class_perm_node_t)); class_perm_node_init(dest_perms); if (!dest_perms) { yyerror("out of memory"); return -1; } if (!dest->perms) dest->perms = dest_perms; else dest_tail->next = dest_perms; dest_perms->tclass = src_perms->tclass; dest_perms->data = src_perms->data; dest_perms->next = NULL; dest_tail = dest_perms; src_perms = src_perms->next; } return 0; } int define_te_avtab_ioctl(avrule_t *avrule_template) { avrule_t *avrule; struct av_ioctl_range_list *rangelist; av_extended_perms_t *complete_driver, *partial_driver, *xperms; unsigned int i; /* organize ioctl ranges */ if (avrule_ioctl_ranges(&rangelist)) return -1; /* create rule for ioctl driver types that are entirely enabled */ if (avrule_ioctl_completedriver(rangelist, &complete_driver)) return -1; if (complete_driver) { avrule = (avrule_t *) calloc(1, sizeof(avrule_t)); if (!avrule) { yyerror("out of memory"); return -1; } if (avrule_cpy(avrule, avrule_template)) return -1; avrule->xperms = complete_driver; append_avrule(avrule); } /* flag ioctl driver codes that are partially enabled */ if (avrule_ioctl_partialdriver(rangelist, complete_driver, &partial_driver)) return -1; if (!partial_driver || !avrule_xperms_used(partial_driver)) goto done; /* * create rule for each partially used driver codes * "partially used" meaning that the code number e.g. socket 0x89 * has some permission bits set and others not set. */ i = 0; while (xperms_for_each_bit(&i, partial_driver)) { if (avrule_ioctl_func(rangelist, &xperms, i)) return -1; if (xperms) { avrule = (avrule_t *) calloc(1, sizeof(avrule_t)); if (!avrule) { yyerror("out of memory"); return -1; } if (avrule_cpy(avrule, avrule_template)) return -1; avrule->xperms = xperms; append_avrule(avrule); } } done: if (partial_driver) free(partial_driver); return 0; } int define_te_avtab_extended_perms(int which) { char *id; unsigned int i; avrule_t *avrule_template; if (pass == 1) { for (i = 0; i < 4; i++) { while ((id = queue_remove(id_queue))) free(id); } return 0; } /* populate avrule template with source/target/tclass */ if (define_te_avtab_xperms_helper(which, &avrule_template)) return -1; id = queue_remove(id_queue); if (strcmp(id,"ioctl") == 0) { free(id); if (define_te_avtab_ioctl(avrule_template)) return -1; } else { yyerror("only ioctl extended permissions are supported"); free(id); return -1; } return 0; } int define_te_avtab_helper(int which, avrule_t ** rule) { char *id; class_datum_t *cladatum; perm_datum_t *perdatum = NULL; class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL; ebitmap_t tclasses; ebitmap_node_t *node; avrule_t *avrule; unsigned int i; int add = 1, ret = 0; int suppress = 0; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) { yyerror("memory error"); ret = -1; goto out; } avrule_init(avrule); avrule->specified = which; avrule->line = policydb_lineno; avrule->source_line = source_lineno; avrule->source_filename = strdup(source_file); avrule->xperms = NULL; if (!avrule->source_filename) { yyerror("out of memory"); return -1; } while ((id = queue_remove(id_queue))) { if (set_types (&avrule->stypes, id, &add, which == AVRULE_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } } add = 1; while ((id = queue_remove(id_queue))) { if (strcmp(id, "self") == 0) { free(id); if (add == 0) { yyerror("-self is not supported"); ret = -1; goto out; } avrule->flags |= RULE_SELF; continue; } if (set_types (&avrule->ttypes, id, &add, which == AVRULE_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } } ebitmap_init(&tclasses); ret = read_classes(&tclasses); if (ret) goto out; perms = NULL; ebitmap_for_each_bit(&tclasses, node, i) { if (!ebitmap_node_get_bit(node, i)) continue; cur_perms = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!cur_perms) { yyerror("out of memory"); ret = -1; goto out; } class_perm_node_init(cur_perms); cur_perms->tclass = i + 1; if (!perms) perms = cur_perms; if (tail) tail->next = cur_perms; tail = cur_perms; } while ((id = queue_remove(id_queue))) { cur_perms = perms; ebitmap_for_each_bit(&tclasses, node, i) { if (!ebitmap_node_get_bit(node, i)) continue; cladatum = policydbp->class_val_to_struct[i]; if (strcmp(id, "*") == 0) { /* set all permissions in the class */ cur_perms->data = ~0U; goto next; } if (strcmp(id, "~") == 0) { /* complement the set */ if (which == AVRULE_DONTAUDIT) yywarn("dontaudit rule with a ~?"); cur_perms->data = ~cur_perms->data; goto next; } perdatum = hashtab_search(cladatum->permissions.table, id); if (!perdatum) { if (cladatum->comdatum) { perdatum = hashtab_search(cladatum->comdatum-> permissions.table, id); } } if (!perdatum) { if (!suppress) yyerror2("permission %s is not defined" " for class %s", id, policydbp->p_class_val_to_name[i]); continue; } else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) { if (!suppress) { yyerror2("permission %s of class %s is" " not within scope", id, policydbp->p_class_val_to_name[i]); } continue; } else { cur_perms->data |= 1U << (perdatum->s.value - 1); } next: cur_perms = cur_perms->next; } free(id); } ebitmap_destroy(&tclasses); avrule->perms = perms; *rule = avrule; out: if (ret) { avrule_destroy(avrule); free(avrule); } return ret; } avrule_t *define_cond_te_avtab(int which) { char *id; avrule_t *avrule; int i; if (pass == 1) { for (i = 0; i < 4; i++) { while ((id = queue_remove(id_queue))) free(id); } return (avrule_t *) 1; /* any non-NULL value */ } if (define_te_avtab_helper(which, &avrule)) return COND_ERR; return avrule; } int define_te_avtab(int which) { char *id; avrule_t *avrule; int i; if (pass == 1) { for (i = 0; i < 4; i++) { while ((id = queue_remove(id_queue))) free(id); } return 0; } if (define_te_avtab_helper(which, &avrule)) return -1; /* append this avrule to the end of the current rules list */ append_avrule(avrule); return 0; } /* The role-types rule is no longer used to declare regular role or * role attribute, but solely aimed for declaring role-types associations. */ int define_role_types(void) { role_datum_t *role; char *id; int add = 1; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no role name for role-types rule?"); return -1; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); return -1; } role = hashtab_search(policydbp->p_roles.table, id); if (!role) { yyerror2("unknown role %s", id); free(id); return -1; } role = get_local_role(id, role->s.value, (role->flavor == ROLE_ATTRIB)); while ((id = queue_remove(id_queue))) { if (set_types(&role->types, id, &add, 0)) return -1; } return 0; } int define_attrib_role(void) { if (pass == 2) { free(queue_remove(id_queue)); return 0; } /* Declare a role attribute */ if (declare_role(TRUE) == NULL) return -1; return 0; } int define_role_attr(void) { char *id; role_datum_t *r, *attr; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } /* Declare a regular role */ if ((r = declare_role(FALSE)) == NULL) return -1; while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("attribute %s is not within scope", id); free(id); return -1; } attr = hashtab_search(policydbp->p_roles.table, id); if (!attr) { /* treat it as a fatal error */ yyerror2("role attribute %s is not declared", id); free(id); return -1; } if (attr->flavor != ROLE_ATTRIB) { yyerror2("%s is a regular role, not an attribute", id); free(id); return -1; } if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) { yyerror("Out of memory!"); return -1; } if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) { yyerror("out of memory"); return -1; } } return 0; } int define_roleattribute(void) { char *id; role_datum_t *r, *attr; if (pass == 2) { while ((id = queue_remove(id_queue))) free(id); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no role name for roleattribute definition?"); return -1; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); return -1; } r = hashtab_search(policydbp->p_roles.table, id); /* We support adding one role attribute into another */ if (!r) { yyerror2("unknown role %s", id); free(id); return -1; } free(id); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("attribute %s is not within scope", id); free(id); return -1; } attr = hashtab_search(policydbp->p_roles.table, id); if (!attr) { /* treat it as a fatal error */ yyerror2("role attribute %s is not declared", id); free(id); return -1; } if (attr->flavor != ROLE_ATTRIB) { yyerror2("%s is a regular role, not an attribute", id); free(id); return -1; } if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) { yyerror("Out of memory!"); return -1; } if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) { yyerror("out of memory"); return -1; } } return 0; } role_datum_t *merge_roles_dom(role_datum_t * r1, role_datum_t * r2) { role_datum_t *new; if (pass == 1) { return (role_datum_t *) 1; /* any non-NULL value */ } new = malloc(sizeof(role_datum_t)); if (!new) { yyerror("out of memory"); return NULL; } memset(new, 0, sizeof(role_datum_t)); new->s.value = 0; /* temporary role */ if (ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) { yyerror("out of memory"); free(new); return NULL; } if (ebitmap_or(&new->types.types, &r1->types.types, &r2->types.types)) { yyerror("out of memory"); free(new); return NULL; } if (!r1->s.value) { /* free intermediate result */ type_set_destroy(&r1->types); ebitmap_destroy(&r1->dominates); free(r1); } if (!r2->s.value) { /* free intermediate result */ yyerror("right hand role is temporary?"); type_set_destroy(&r2->types); ebitmap_destroy(&r2->dominates); free(r2); } return new; } /* This function eliminates the ordering dependency of role dominance rule */ static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { role_datum_t *rdp = (role_datum_t *) arg; role_datum_t *rdatum = (role_datum_t *) datum; ebitmap_node_t *node; uint32_t i; /* Don't bother to process against self role */ if (rdatum->s.value == rdp->s.value) return 0; /* If a dominating role found */ if (ebitmap_get_bit(&(rdatum->dominates), rdp->s.value - 1)) { ebitmap_t types; ebitmap_init(&types); if (type_set_expand(&rdp->types, &types, policydbp, 1)) { ebitmap_destroy(&types); return -1; } /* raise types and dominates from dominated role */ ebitmap_for_each_bit(&rdp->dominates, node, i) { if (ebitmap_node_get_bit(node, i)) if (ebitmap_set_bit (&rdatum->dominates, i, TRUE)) goto oom; } ebitmap_for_each_bit(&types, node, i) { if (ebitmap_node_get_bit(node, i)) if (ebitmap_set_bit (&rdatum->types.types, i, TRUE)) goto oom; } ebitmap_destroy(&types); } /* go through all the roles */ return 0; oom: yyerror("Out of memory"); return -1; } role_datum_t *define_role_dom(role_datum_t * r) { role_datum_t *role; char *role_id; ebitmap_node_t *node; unsigned int i; int ret; if (pass == 1) { role_id = queue_remove(id_queue); free(role_id); return (role_datum_t *) 1; /* any non-NULL value */ } yywarn("Role dominance has been deprecated"); role_id = queue_remove(id_queue); if (!is_id_in_scope(SYM_ROLES, role_id)) { yyerror2("role %s is not within scope", role_id); free(role_id); return NULL; } role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, role_id); if (!role) { role = (role_datum_t *) malloc(sizeof(role_datum_t)); if (!role) { yyerror("out of memory"); free(role_id); return NULL; } memset(role, 0, sizeof(role_datum_t)); ret = declare_symbol(SYM_ROLES, (hashtab_key_t) role_id, (hashtab_datum_t) role, &role->s.value, &role->s.value); switch (ret) { case -3:{ yyerror("Out of memory!"); goto cleanup; } case -2:{ yyerror2("duplicate declaration of role %s", role_id); goto cleanup; } case -1:{ yyerror("could not declare role here"); goto cleanup; } case 0: case 1:{ break; } default:{ assert(0); /* should never get here */ } } if (ebitmap_set_bit(&role->dominates, role->s.value - 1, TRUE)) { yyerror("Out of memory!"); goto cleanup; } } if (r) { ebitmap_t types; ebitmap_init(&types); ebitmap_for_each_bit(&r->dominates, node, i) { if (ebitmap_node_get_bit(node, i)) if (ebitmap_set_bit(&role->dominates, i, TRUE)) goto oom; } if (type_set_expand(&r->types, &types, policydbp, 1)) { ebitmap_destroy(&types); return NULL; } ebitmap_for_each_bit(&types, node, i) { if (ebitmap_node_get_bit(node, i)) if (ebitmap_set_bit (&role->types.types, i, TRUE)) goto oom; } ebitmap_destroy(&types); if (!r->s.value) { /* free intermediate result */ type_set_destroy(&r->types); ebitmap_destroy(&r->dominates); free(r); } /* * Now go through all the roles and escalate this role's * dominates and types if a role dominates this role. */ hashtab_map(policydbp->p_roles.table, dominate_role_recheck, role); } return role; cleanup: free(role_id); role_datum_destroy(role); free(role); return NULL; oom: yyerror("Out of memory"); goto cleanup; } static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p) { struct val_to_name *v = p; role_datum_t *roldatum; roldatum = (role_datum_t *) datum; if (v->val == roldatum->s.value) { v->name = key; return 1; } return 0; } static char *role_val_to_name(unsigned int val) { struct val_to_name v; int rc; v.val = val; rc = hashtab_map(policydbp->p_roles.table, role_val_to_name_helper, &v); if (rc) return v.name; return NULL; } static int set_roles(role_set_t * set, char *id) { role_datum_t *r; if (strcmp(id, "*") == 0) { free(id); yyerror("* is not allowed for role sets"); return -1; } if (strcmp(id, "~") == 0) { free(id); yyerror("~ is not allowed for role sets"); return -1; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); return -1; } r = hashtab_search(policydbp->p_roles.table, id); if (!r) { yyerror2("unknown role %s", id); free(id); return -1; } if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE)) { yyerror("out of memory"); free(id); return -1; } free(id); return 0; } int define_role_trans(int class_specified) { char *id; role_datum_t *role; role_set_t roles; type_set_t types; class_datum_t *cladatum; ebitmap_t e_types, e_roles, e_classes; ebitmap_node_t *tnode, *rnode, *cnode; struct role_trans *tr = NULL; struct role_trans_rule *rule = NULL; unsigned int i, j, k; int add = 1; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); if (class_specified) while ((id = queue_remove(id_queue))) free(id); id = queue_remove(id_queue); free(id); return 0; } role_set_init(&roles); ebitmap_init(&e_roles); type_set_init(&types); ebitmap_init(&e_types); ebitmap_init(&e_classes); while ((id = queue_remove(id_queue))) { if (set_roles(&roles, id)) return -1; } add = 1; while ((id = queue_remove(id_queue))) { if (set_types(&types, id, &add, 0)) return -1; } if (class_specified) { if (read_classes(&e_classes)) return -1; } else { cladatum = hashtab_search(policydbp->p_classes.table, "process"); if (!cladatum) { yyerror2("could not find process class for " "legacy role_transition statement"); return -1; } if (ebitmap_set_bit(&e_classes, cladatum->s.value - 1, TRUE)) { yyerror("out of memory"); return -1; } } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no new role in transition definition?"); goto bad; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); goto bad; } role = hashtab_search(policydbp->p_roles.table, id); if (!role) { yyerror2("unknown role %s used in transition definition", id); free(id); goto bad; } if (role->flavor != ROLE_ROLE) { yyerror2("the new role %s must be a regular role", id); free(id); goto bad; } free(id); /* This ebitmap business is just to ensure that there are not conflicting role_trans rules */ if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL)) goto bad; if (type_set_expand(&types, &e_types, policydbp, 1)) goto bad; ebitmap_for_each_bit(&e_roles, rnode, i) { if (!ebitmap_node_get_bit(rnode, i)) continue; ebitmap_for_each_bit(&e_types, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; ebitmap_for_each_bit(&e_classes, cnode, k) { if (!ebitmap_node_get_bit(cnode, k)) continue; for (tr = policydbp->role_tr; tr; tr = tr->next) { if (tr->role == (i + 1) && tr->type == (j + 1) && tr->tclass == (k + 1)) { yyerror2("duplicate role " "transition for " "(%s,%s,%s)", role_val_to_name(i+1), policydbp->p_type_val_to_name[j], policydbp->p_class_val_to_name[k]); goto bad; } } tr = malloc(sizeof(struct role_trans)); if (!tr) { yyerror("out of memory"); return -1; } memset(tr, 0, sizeof(struct role_trans)); tr->role = i + 1; tr->type = j + 1; tr->tclass = k + 1; tr->new_role = role->s.value; tr->next = policydbp->role_tr; policydbp->role_tr = tr; } } } /* Now add the real rule */ rule = malloc(sizeof(struct role_trans_rule)); if (!rule) { yyerror("out of memory"); return -1; } memset(rule, 0, sizeof(struct role_trans_rule)); rule->roles = roles; rule->types = types; rule->classes = e_classes; rule->new_role = role->s.value; append_role_trans(rule); ebitmap_destroy(&e_roles); ebitmap_destroy(&e_types); return 0; bad: return -1; } int define_role_allow(void) { char *id; struct role_allow_rule *ra = 0; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); return 0; } ra = malloc(sizeof(role_allow_rule_t)); if (!ra) { yyerror("out of memory"); return -1; } role_allow_rule_init(ra); while ((id = queue_remove(id_queue))) { if (set_roles(&ra->roles, id)) { free(ra); return -1; } } while ((id = queue_remove(id_queue))) { if (set_roles(&ra->new_roles, id)) { free(ra); return -1; } } append_role_allow(ra); return 0; } avrule_t *define_cond_filename_trans(void) { yyerror("type transitions with a filename not allowed inside " "conditionals\n"); return COND_ERR; } int define_filename_trans(void) { char *id, *name = NULL; type_set_t stypes, ttypes; ebitmap_t e_stypes, e_ttypes; ebitmap_t e_tclasses; ebitmap_node_t *snode, *tnode, *cnode; filename_trans_t *ft; filename_trans_datum_t *ftdatum; filename_trans_rule_t *ftr; type_datum_t *typdatum; uint32_t otype; unsigned int c, s, t; int add, rc; if (pass == 1) { /* stype */ while ((id = queue_remove(id_queue))) free(id); /* ttype */ while ((id = queue_remove(id_queue))) free(id); /* tclass */ while ((id = queue_remove(id_queue))) free(id); /* otype */ id = queue_remove(id_queue); free(id); /* name */ id = queue_remove(id_queue); free(id); return 0; } type_set_init(&stypes); type_set_init(&ttypes); ebitmap_init(&e_stypes); ebitmap_init(&e_ttypes); ebitmap_init(&e_tclasses); add = 1; while ((id = queue_remove(id_queue))) { if (set_types(&stypes, id, &add, 0)) goto bad; } add =1; while ((id = queue_remove(id_queue))) { if (set_types(&ttypes, id, &add, 0)) goto bad; } if (read_classes(&e_tclasses)) goto bad; id = (char *)queue_remove(id_queue); if (!id) { yyerror("no otype in transition definition?"); goto bad; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); goto bad; } typdatum = hashtab_search(policydbp->p_types.table, id); if (!typdatum) { yyerror2("unknown type %s used in transition definition", id); free(id); goto bad; } free(id); otype = typdatum->s.value; name = queue_remove(id_queue); if (!name) { yyerror("no pathname specified in filename_trans definition?"); goto bad; } /* We expand the class set into seperate rules. We expand the types * just to make sure there are not duplicates. They will get turned * into seperate rules later */ if (type_set_expand(&stypes, &e_stypes, policydbp, 1)) goto bad; if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1)) goto bad; ebitmap_for_each_bit(&e_tclasses, cnode, c) { if (!ebitmap_node_get_bit(cnode, c)) continue; ebitmap_for_each_bit(&e_stypes, snode, s) { if (!ebitmap_node_get_bit(snode, s)) continue; ebitmap_for_each_bit(&e_ttypes, tnode, t) { if (!ebitmap_node_get_bit(tnode, t)) continue; ft = calloc(1, sizeof(*ft)); if (!ft) { yyerror("out of memory"); goto bad; } ft->stype = s+1; ft->ttype = t+1; ft->tclass = c+1; ft->name = strdup(name); if (!ft->name) { yyerror("out of memory"); goto bad; } ftdatum = hashtab_search(policydbp->filename_trans, (hashtab_key_t)ft); if (ftdatum) { yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s", name, policydbp->p_type_val_to_name[s], policydbp->p_type_val_to_name[t], policydbp->p_class_val_to_name[c]); goto bad; } ftdatum = calloc(1, sizeof(*ftdatum)); if (!ftdatum) { yyerror("out of memory"); goto bad; } rc = hashtab_insert(policydbp->filename_trans, (hashtab_key_t)ft, ftdatum); if (rc) { yyerror("out of memory"); goto bad; } } } /* Now add the real rule since we didn't find any duplicates */ ftr = malloc(sizeof(*ftr)); if (!ftr) { yyerror("out of memory"); goto bad; } filename_trans_rule_init(ftr); append_filename_trans(ftr); ftr->name = strdup(name); if (type_set_cpy(&ftr->stypes, &stypes)) { yyerror("out of memory"); goto bad; } if (type_set_cpy(&ftr->ttypes, &ttypes)) { yyerror("out of memory"); goto bad; } ftr->tclass = c + 1; ftr->otype = otype; } free(name); ebitmap_destroy(&e_stypes); ebitmap_destroy(&e_ttypes); ebitmap_destroy(&e_tclasses); type_set_destroy(&stypes); type_set_destroy(&ttypes); return 0; bad: free(name); ebitmap_destroy(&e_stypes); ebitmap_destroy(&e_ttypes); ebitmap_destroy(&e_tclasses); type_set_destroy(&stypes); type_set_destroy(&ttypes); return -1; } static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr) { constraint_expr_t *h = NULL, *l = NULL, *e, *newe; for (e = expr; e; e = e->next) { newe = malloc(sizeof(*newe)); if (!newe) goto oom; if (constraint_expr_init(newe) == -1) { free(newe); goto oom; } if (l) l->next = newe; else h = newe; l = newe; newe->expr_type = e->expr_type; newe->attr = e->attr; newe->op = e->op; if (newe->expr_type == CEXPR_NAMES) { if (newe->attr & CEXPR_TYPE) { if (type_set_cpy (newe->type_names, e->type_names)) goto oom; } else { if (ebitmap_cpy(&newe->names, &e->names)) goto oom; } } } return h; oom: e = h; while (e) { l = e; e = e->next; constraint_expr_destroy(l); } return NULL; } int define_constraint(constraint_expr_t * expr) { struct constraint_node *node; char *id; class_datum_t *cladatum; perm_datum_t *perdatum; ebitmap_t classmap; ebitmap_node_t *enode; constraint_expr_t *e; unsigned int i; int depth; unsigned char useexpr = 1; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); return 0; } depth = -1; for (e = expr; e; e = e->next) { switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) { yyerror("illegal constraint expression"); return -1; } break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) { yyerror("illegal constraint expression"); return -1; } depth--; break; case CEXPR_ATTR: case CEXPR_NAMES: if (e->attr & CEXPR_XTARGET) { yyerror("illegal constraint expression"); return -1; /* only for validatetrans rules */ } if (depth == (CEXPR_MAXDEPTH - 1)) { yyerror("constraint expression is too deep"); return -1; } depth++; break; default: yyerror("illegal constraint expression"); return -1; } } if (depth != 0) { yyerror("illegal constraint expression"); return -1; } ebitmap_init(&classmap); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); free(id); return -1; } cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, (hashtab_key_t) id); if (!cladatum) { yyerror2("class %s is not defined", id); ebitmap_destroy(&classmap); free(id); return -1; } if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) { yyerror("out of memory"); ebitmap_destroy(&classmap); free(id); return -1; } node = malloc(sizeof(struct constraint_node)); if (!node) { yyerror("out of memory"); free(node); return -1; } memset(node, 0, sizeof(constraint_node_t)); if (useexpr) { node->expr = expr; useexpr = 0; } else { node->expr = constraint_expr_clone(expr); } if (!node->expr) { yyerror("out of memory"); free(node); return -1; } node->permissions = 0; node->next = cladatum->constraints; cladatum->constraints = node; free(id); } while ((id = queue_remove(id_queue))) { ebitmap_for_each_bit(&classmap, enode, i) { if (ebitmap_node_get_bit(enode, i)) { cladatum = policydbp->class_val_to_struct[i]; node = cladatum->constraints; perdatum = (perm_datum_t *) hashtab_search(cladatum-> permissions. table, (hashtab_key_t) id); if (!perdatum) { if (cladatum->comdatum) { perdatum = (perm_datum_t *) hashtab_search(cladatum-> comdatum-> permissions. table, (hashtab_key_t) id); } if (!perdatum) { yyerror2("permission %s is not" " defined", id); free(id); ebitmap_destroy(&classmap); return -1; } } node->permissions |= (1 << (perdatum->s.value - 1)); } } free(id); } ebitmap_destroy(&classmap); return 0; } int define_validatetrans(constraint_expr_t * expr) { struct constraint_node *node; char *id; class_datum_t *cladatum; ebitmap_t classmap; constraint_expr_t *e; int depth; unsigned char useexpr = 1; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); return 0; } depth = -1; for (e = expr; e; e = e->next) { switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) { yyerror("illegal validatetrans expression"); return -1; } break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) { yyerror("illegal validatetrans expression"); return -1; } depth--; break; case CEXPR_ATTR: case CEXPR_NAMES: if (depth == (CEXPR_MAXDEPTH - 1)) { yyerror("validatetrans expression is too deep"); return -1; } depth++; break; default: yyerror("illegal validatetrans expression"); return -1; } } if (depth != 0) { yyerror("illegal validatetrans expression"); return -1; } ebitmap_init(&classmap); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); free(id); return -1; } cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, (hashtab_key_t) id); if (!cladatum) { yyerror2("class %s is not defined", id); ebitmap_destroy(&classmap); free(id); return -1; } if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) { yyerror("out of memory"); ebitmap_destroy(&classmap); free(id); return -1; } node = malloc(sizeof(struct constraint_node)); if (!node) { yyerror("out of memory"); return -1; } memset(node, 0, sizeof(constraint_node_t)); if (useexpr) { node->expr = expr; useexpr = 0; } else { node->expr = constraint_expr_clone(expr); } node->permissions = 0; node->next = cladatum->validatetrans; cladatum->validatetrans = node; free(id); } ebitmap_destroy(&classmap); return 0; } uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) { struct constraint_expr *expr, *e1 = NULL, *e2; user_datum_t *user; role_datum_t *role; ebitmap_t negset; char *id; uint32_t val; int add = 1; if (pass == 1) { if (expr_type == CEXPR_NAMES) { while ((id = queue_remove(id_queue))) free(id); } return 1; /* any non-NULL value */ } if ((expr = malloc(sizeof(*expr))) == NULL || constraint_expr_init(expr) == -1) { yyerror("out of memory"); free(expr); return 0; } expr->expr_type = expr_type; switch (expr_type) { case CEXPR_NOT: e1 = NULL; e2 = (struct constraint_expr *)arg1; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror("illegal constraint expression"); constraint_expr_destroy(expr); return 0; } e1->next = expr; return arg1; case CEXPR_AND: case CEXPR_OR: e1 = NULL; e2 = (struct constraint_expr *)arg1; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror("illegal constraint expression"); constraint_expr_destroy(expr); return 0; } e1->next = (struct constraint_expr *)arg2; e1 = NULL; e2 = (struct constraint_expr *)arg2; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror("illegal constraint expression"); constraint_expr_destroy(expr); return 0; } e1->next = expr; return arg1; case CEXPR_ATTR: expr->attr = arg1; expr->op = arg2; return (uintptr_t) expr; case CEXPR_NAMES: add = 1; expr->attr = arg1; expr->op = arg2; ebitmap_init(&negset); while ((id = (char *)queue_remove(id_queue))) { if (expr->attr & CEXPR_USER) { if (!is_id_in_scope(SYM_USERS, id)) { yyerror2("user %s is not within scope", id); constraint_expr_destroy(expr); return 0; } user = (user_datum_t *) hashtab_search(policydbp-> p_users. table, (hashtab_key_t) id); if (!user) { yyerror2("unknown user %s", id); constraint_expr_destroy(expr); return 0; } val = user->s.value; } else if (expr->attr & CEXPR_ROLE) { if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); constraint_expr_destroy(expr); return 0; } role = (role_datum_t *) hashtab_search(policydbp-> p_roles. table, (hashtab_key_t) id); if (!role) { yyerror2("unknown role %s", id); constraint_expr_destroy(expr); return 0; } val = role->s.value; } else if (expr->attr & CEXPR_TYPE) { if (set_types(expr->type_names, id, &add, 0)) { constraint_expr_destroy(expr); return 0; } continue; } else { yyerror("invalid constraint expression"); constraint_expr_destroy(expr); return 0; } if (ebitmap_set_bit(&expr->names, val - 1, TRUE)) { yyerror("out of memory"); ebitmap_destroy(&expr->names); constraint_expr_destroy(expr); return 0; } free(id); } ebitmap_destroy(&negset); return (uintptr_t) expr; default: break; } yyerror("invalid constraint expression"); constraint_expr_destroy(expr); return 0; } int define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f) { cond_expr_t *e; int depth; cond_node_t cn, *cn_old; /* expression cannot be NULL */ if (!expr) { yyerror("illegal conditional expression"); return -1; } if (!t) { if (!f) { /* empty is fine, destroy expression and return */ cond_expr_destroy(expr); return 0; } /* Invert */ t = f; f = 0; expr = define_cond_expr(COND_NOT, expr, 0); if (!expr) { yyerror("unable to invert"); return -1; } } /* verify expression */ depth = -1; for (e = expr; e; e = e->next) { switch (e->expr_type) { case COND_NOT: if (depth < 0) { yyerror ("illegal conditional expression; Bad NOT"); return -1; } break; case COND_AND: case COND_OR: case COND_XOR: case COND_EQ: case COND_NEQ: if (depth < 1) { yyerror ("illegal conditional expression; Bad binary op"); return -1; } depth--; break; case COND_BOOL: if (depth == (COND_EXPR_MAXDEPTH - 1)) { yyerror ("conditional expression is like totally too deep"); return -1; } depth++; break; default: yyerror("illegal conditional expression"); return -1; } } if (depth != 0) { yyerror("illegal conditional expression"); return -1; } /* use tmp conditional node to partially build new node */ memset(&cn, 0, sizeof(cn)); cn.expr = expr; cn.avtrue_list = t; cn.avfalse_list = f; /* normalize/precompute expression */ if (cond_normalize_expr(policydbp, &cn) < 0) { yyerror("problem normalizing conditional expression"); return -1; } /* get the existing conditional node, or create a new one */ cn_old = get_current_cond_list(&cn); if (!cn_old) { return -1; } append_cond_list(&cn); /* note that there is no check here for duplicate rules, nor * check that rule already exists in base -- that will be * handled during conditional expansion, in expand.c */ cn.avtrue_list = NULL; cn.avfalse_list = NULL; cond_node_destroy(&cn); return 0; } cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2) { struct cond_expr *expr, *e1 = NULL, *e2; cond_bool_datum_t *bool_var; char *id; /* expressions are handled in the second pass */ if (pass == 1) { if (expr_type == COND_BOOL) { while ((id = queue_remove(id_queue))) { free(id); } } return (cond_expr_t *) 1; /* any non-NULL value */ } /* create a new expression struct */ expr = malloc(sizeof(struct cond_expr)); if (!expr) { yyerror("out of memory"); return NULL; } memset(expr, 0, sizeof(cond_expr_t)); expr->expr_type = expr_type; /* create the type asked for */ switch (expr_type) { case COND_NOT: e1 = NULL; e2 = (struct cond_expr *)arg1; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror("illegal conditional NOT expression"); free(expr); return NULL; } e1->next = expr; return (struct cond_expr *)arg1; case COND_AND: case COND_OR: case COND_XOR: case COND_EQ: case COND_NEQ: e1 = NULL; e2 = (struct cond_expr *)arg1; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror ("illegal left side of conditional binary op expression"); free(expr); return NULL; } e1->next = (struct cond_expr *)arg2; e1 = NULL; e2 = (struct cond_expr *)arg2; while (e2) { e1 = e2; e2 = e2->next; } if (!e1 || e1->next) { yyerror ("illegal right side of conditional binary op expression"); free(expr); return NULL; } e1->next = expr; return (struct cond_expr *)arg1; case COND_BOOL: id = (char *)queue_remove(id_queue); if (!id) { yyerror("bad conditional; expected boolean id"); free(id); free(expr); return NULL; } if (!is_id_in_scope(SYM_BOOLS, id)) { yyerror2("boolean %s is not within scope", id); free(id); free(expr); return NULL; } bool_var = (cond_bool_datum_t *) hashtab_search(policydbp->p_bools. table, (hashtab_key_t) id); if (!bool_var) { yyerror2("unknown boolean %s in conditional expression", id); free(expr); free(id); return NULL; } expr->bool = bool_var->s.value; free(id); return expr; default: yyerror("illegal conditional expression"); free(expr); return NULL; } } static int set_user_roles(role_set_t * set, char *id) { role_datum_t *r; unsigned int i; ebitmap_node_t *node; if (strcmp(id, "*") == 0) { free(id); yyerror("* is not allowed in user declarations"); return -1; } if (strcmp(id, "~") == 0) { free(id); yyerror("~ is not allowed in user declarations"); return -1; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); return -1; } r = hashtab_search(policydbp->p_roles.table, id); if (!r) { yyerror2("unknown role %s", id); free(id); return -1; } /* set the role and every role it dominates */ ebitmap_for_each_bit(&r->dominates, node, i) { if (ebitmap_node_get_bit(node, i)) if (ebitmap_set_bit(&set->roles, i, TRUE)) goto oom; } free(id); return 0; oom: yyerror("out of memory"); return -1; } static int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats) { cat_datum_t *cdatum; int range_start, range_end, i; if (id_has_dot(id)) { char *id_start = id; char *id_end = strchr(id, '.'); *(id_end++) = '\0'; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id_start); if (!cdatum) { yyerror2("unknown category %s", id_start); return -1; } range_start = cdatum->s.value - 1; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id_end); if (!cdatum) { yyerror2("unknown category %s", id_end); return -1; } range_end = cdatum->s.value - 1; if (range_end < range_start) { yyerror2("category range is invalid"); return -1; } } else { cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id); if (!cdatum) { yyerror2("unknown category %s", id); return -1; } range_start = range_end = cdatum->s.value - 1; } for (i = range_start; i <= range_end; i++) { if (!ebitmap_get_bit(&levdatum->level->cat, i)) { uint32_t level_value = levdatum->level->sens - 1; policydb_index_others(NULL, policydbp, 0); yyerror2("category %s can not be associated " "with level %s", policydbp->p_cat_val_to_name[i], policydbp->p_sens_val_to_name[level_value]); return -1; } if (ebitmap_set_bit(cats, i, TRUE)) { yyerror("out of memory"); return -1; } } return 0; } static int parse_semantic_categories(char *id, level_datum_t * levdatum __attribute__ ((unused)), mls_semantic_cat_t ** cats) { cat_datum_t *cdatum; mls_semantic_cat_t *newcat; unsigned int range_start, range_end; if (id_has_dot(id)) { char *id_start = id; char *id_end = strchr(id, '.'); *(id_end++) = '\0'; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id_start); if (!cdatum) { yyerror2("unknown category %s", id_start); return -1; } range_start = cdatum->s.value; cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id_end); if (!cdatum) { yyerror2("unknown category %s", id_end); return -1; } range_end = cdatum->s.value; } else { cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, (hashtab_key_t) id); if (!cdatum) { yyerror2("unknown category %s", id); return -1; } range_start = range_end = cdatum->s.value; } newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!newcat) { yyerror("out of memory"); return -1; } mls_semantic_cat_init(newcat); newcat->next = *cats; newcat->low = range_start; newcat->high = range_end; *cats = newcat; return 0; } int define_user(void) { char *id; user_datum_t *usrdatum; level_datum_t *levdatum; int l; if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); if (mlspol) { while ((id = queue_remove(id_queue))) free(id); id = queue_remove(id_queue); free(id); for (l = 0; l < 2; l++) { while ((id = queue_remove(id_queue))) { free(id); } id = queue_remove(id_queue); if (!id) break; free(id); } } return 0; } if ((usrdatum = declare_user()) == NULL) { return -1; } while ((id = queue_remove(id_queue))) { if (set_user_roles(&usrdatum->roles, id)) continue; } if (mlspol) { id = queue_remove(id_queue); if (!id) { yyerror("no default level specified for user"); return -1; } levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, (hashtab_key_t) id); if (!levdatum) { yyerror2("unknown sensitivity %s used in user" " level definition", id); free(id); return -1; } free(id); usrdatum->dfltlevel.sens = levdatum->level->sens; while ((id = queue_remove(id_queue))) { if (parse_semantic_categories(id, levdatum, &usrdatum->dfltlevel.cat)) { free(id); return -1; } free(id); } id = queue_remove(id_queue); for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, (hashtab_key_t) id); if (!levdatum) { yyerror2("unknown sensitivity %s used in user" " range definition", id); free(id); return -1; } free(id); usrdatum->range.level[l].sens = levdatum->level->sens; while ((id = queue_remove(id_queue))) { if (parse_semantic_categories(id, levdatum, &usrdatum->range.level[l].cat)) { free(id); return -1; } free(id); } id = queue_remove(id_queue); if (!id) break; } if (l == 0) { if (mls_semantic_level_cpy(&usrdatum->range.level[1], &usrdatum->range.level[0])) { yyerror("out of memory"); return -1; } } } return 0; } static int parse_security_context(context_struct_t * c) { char *id; role_datum_t *role; type_datum_t *typdatum; user_datum_t *usrdatum; level_datum_t *levdatum; int l; if (pass == 1) { id = queue_remove(id_queue); free(id); /* user */ id = queue_remove(id_queue); free(id); /* role */ id = queue_remove(id_queue); free(id); /* type */ if (mlspol) { id = queue_remove(id_queue); free(id); for (l = 0; l < 2; l++) { while ((id = queue_remove(id_queue))) { free(id); } id = queue_remove(id_queue); if (!id) break; free(id); } } return 0; } /* check context c to make sure ok to dereference c later */ if (c == NULL) { yyerror("null context pointer!"); return -1; } context_init(c); /* extract the user */ id = queue_remove(id_queue); if (!id) { yyerror("no effective user?"); goto bad; } if (!is_id_in_scope(SYM_USERS, id)) { yyerror2("user %s is not within scope", id); free(id); goto bad; } usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table, (hashtab_key_t) id); if (!usrdatum) { yyerror2("user %s is not defined", id); free(id); goto bad; } c->user = usrdatum->s.value; /* no need to keep the user name */ free(id); /* extract the role */ id = (char *)queue_remove(id_queue); if (!id) { yyerror("no role name for sid context definition?"); return -1; } if (!is_id_in_scope(SYM_ROLES, id)) { yyerror2("role %s is not within scope", id); free(id); return -1; } role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, (hashtab_key_t) id); if (!role) { yyerror2("role %s is not defined", id); free(id); return -1; } c->role = role->s.value; /* no need to keep the role name */ free(id); /* extract the type */ id = (char *)queue_remove(id_queue); if (!id) { yyerror("no type name for sid context definition?"); return -1; } if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("type %s is not within scope", id); free(id); return -1; } typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table, (hashtab_key_t) id); if (!typdatum || typdatum->flavor == TYPE_ATTRIB) { yyerror2("type %s is not defined or is an attribute", id); free(id); return -1; } c->type = typdatum->s.value; /* no need to keep the type name */ free(id); if (mlspol) { /* extract the low sensitivity */ id = (char *)queue_head(id_queue); if (!id) { yyerror("no sensitivity name for sid context" " definition?"); return -1; } id = (char *)queue_remove(id_queue); for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, (hashtab_key_t) id); if (!levdatum) { yyerror2("Sensitivity %s is not defined", id); free(id); return -1; } free(id); c->range.level[l].sens = levdatum->level->sens; /* extract low category set */ while ((id = queue_remove(id_queue))) { if (parse_categories(id, levdatum, &c->range.level[l].cat)) { free(id); return -1; } free(id); } /* extract high sensitivity */ id = (char *)queue_remove(id_queue); if (!id) break; } if (l == 0) { c->range.level[1].sens = c->range.level[0].sens; if (ebitmap_cpy(&c->range.level[1].cat, &c->range.level[0].cat)) { yyerror("out of memory"); goto bad; } } } if (!policydb_context_isvalid(policydbp, c)) { yyerror("invalid security context"); goto bad; } return 0; bad: context_destroy(c); return -1; } int define_initial_sid_context(void) { char *id; ocontext_t *c, *head; if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no sid name for SID context definition?"); return -1; } head = policydbp->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { if (!strcmp(id, c->u.name)) break; } if (!c) { yyerror2("SID %s is not defined", id); free(id); return -1; } if (c->context[0].user) { yyerror2("The context for SID %s is multiply defined", id); free(id); return -1; } /* no need to keep the sid name */ free(id); if (parse_security_context(&c->context[0])) return -1; return 0; } int define_fs_context(unsigned int major, unsigned int minor) { ocontext_t *newc, *c, *head; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("fscon not supported for target"); return -1; } if (pass == 1) { parse_security_context(NULL); parse_security_context(NULL); return 0; } newc = (ocontext_t *) malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = (char *)malloc(6); if (!newc->u.name) { yyerror("out of memory"); free(newc); return -1; } sprintf(newc->u.name, "%02x:%02x", major, minor); if (parse_security_context(&newc->context[0])) { free(newc->u.name); free(newc); return -1; } if (parse_security_context(&newc->context[1])) { context_destroy(&newc->context[0]); free(newc->u.name); free(newc); return -1; } head = policydbp->ocontexts[OCON_FS]; for (c = head; c; c = c->next) { if (!strcmp(newc->u.name, c->u.name)) { yyerror2("duplicate entry for file system %s", newc->u.name); context_destroy(&newc->context[0]); context_destroy(&newc->context[1]); free(newc->u.name); free(newc); return -1; } } newc->next = head; policydbp->ocontexts[OCON_FS] = newc; return 0; } int define_pirq_context(unsigned int pirq) { ocontext_t *newc, *c, *l, *head; char *id; if (policydbp->target_platform != SEPOL_TARGET_XEN) { yyerror("pirqcon not supported for target"); return -1; } if (pass == 1) { id = (char *) queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.pirq = pirq; if (parse_security_context(&newc->context[0])) { free(newc); return -1; } head = policydbp->ocontexts[OCON_XEN_PIRQ]; for (l = NULL, c = head; c; l = c, c = c->next) { unsigned int pirq2; pirq2 = c->u.pirq; if (pirq == pirq2) { yyerror2("duplicate pirqcon entry for %d ", pirq); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_XEN_PIRQ] = newc; return 0; bad: free(newc); return -1; } int define_iomem_context(uint64_t low, uint64_t high) { ocontext_t *newc, *c, *l, *head; char *id; if (policydbp->target_platform != SEPOL_TARGET_XEN) { yyerror("iomemcon not supported for target"); return -1; } if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.iomem.low_iomem = low; newc->u.iomem.high_iomem = high; if (low > high) { yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high); free(newc); return -1; } if (parse_security_context(&newc->context[0])) { free(newc); return -1; } head = policydbp->ocontexts[OCON_XEN_IOMEM]; for (l = NULL, c = head; c; l = c, c = c->next) { uint64_t low2, high2; low2 = c->u.iomem.low_iomem; high2 = c->u.iomem.high_iomem; if (low <= high2 && low2 <= high) { yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with " "earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high, low2, high2); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_XEN_IOMEM] = newc; return 0; bad: free(newc); return -1; } int define_ioport_context(unsigned long low, unsigned long high) { ocontext_t *newc, *c, *l, *head; char *id; if (policydbp->target_platform != SEPOL_TARGET_XEN) { yyerror("ioportcon not supported for target"); return -1; } if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.ioport.low_ioport = low; newc->u.ioport.high_ioport = high; if (low > high) { yyerror2("low ioport 0x%lx exceeds high ioport 0x%lx", low, high); free(newc); return -1; } if (parse_security_context(&newc->context[0])) { free(newc); return -1; } head = policydbp->ocontexts[OCON_XEN_IOPORT]; for (l = NULL, c = head; c; l = c, c = c->next) { uint32_t low2, high2; low2 = c->u.ioport.low_ioport; high2 = c->u.ioport.high_ioport; if (low <= high2 && low2 <= high) { yyerror2("ioportcon entry for 0x%lx-0x%lx overlaps with" "earlier entry 0x%x-0x%x", low, high, low2, high2); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_XEN_IOPORT] = newc; return 0; bad: free(newc); return -1; } int define_pcidevice_context(unsigned long device) { ocontext_t *newc, *c, *l, *head; char *id; if (policydbp->target_platform != SEPOL_TARGET_XEN) { yyerror("pcidevicecon not supported for target"); return -1; } if (pass == 1) { id = (char *) queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.device = device; if (parse_security_context(&newc->context[0])) { free(newc); return -1; } head = policydbp->ocontexts[OCON_XEN_PCIDEVICE]; for (l = NULL, c = head; c; l = c, c = c->next) { unsigned int device2; device2 = c->u.device; if (device == device2) { yyerror2("duplicate pcidevicecon entry for 0x%lx", device); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_XEN_PCIDEVICE] = newc; return 0; bad: free(newc); return -1; } int define_devicetree_context() { ocontext_t *newc, *c, *l, *head; if (policydbp->target_platform != SEPOL_TARGET_XEN) { yyerror("devicetreecon not supported for target"); return -1; } if (pass == 1) { free(queue_remove(id_queue)); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = (char *)queue_remove(id_queue); if (!newc->u.name) { free(newc); return -1; } if (parse_security_context(&newc->context[0])) { free(newc->u.name); free(newc); return -1; } head = policydbp->ocontexts[OCON_XEN_DEVICETREE]; for (l = NULL, c = head; c; l = c, c = c->next) { if (strcmp(newc->u.name, c->u.name) == 0) { yyerror2("duplicate devicetree entry for '%s'", newc->u.name); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_XEN_DEVICETREE] = newc; return 0; bad: free(newc->u.name); free(newc); return -1; } int define_port_context(unsigned int low, unsigned int high) { ocontext_t *newc, *c, *l, *head; unsigned int protocol; char *id; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("portcon not supported for target"); return -1; } if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); id = (char *)queue_remove(id_queue); if (!id) { free(newc); return -1; } if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) { protocol = IPPROTO_TCP; } else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) { protocol = IPPROTO_UDP; } else if ((strcmp(id, "dccp") == 0) || (strcmp(id, "DCCP") == 0)) { protocol = IPPROTO_DCCP; } else if ((strcmp(id, "sctp") == 0) || (strcmp(id, "SCTP") == 0)) { protocol = IPPROTO_SCTP; } else { yyerror2("unrecognized protocol %s", id); goto bad; } newc->u.port.protocol = protocol; newc->u.port.low_port = low; newc->u.port.high_port = high; if (low > high) { yyerror2("low port %d exceeds high port %d", low, high); goto bad; } if (parse_security_context(&newc->context[0])) { goto bad; } /* Preserve the matching order specified in the configuration. */ head = policydbp->ocontexts[OCON_PORT]; for (l = NULL, c = head; c; l = c, c = c->next) { unsigned int prot2, low2, high2; prot2 = c->u.port.protocol; low2 = c->u.port.low_port; high2 = c->u.port.high_port; if (protocol != prot2) continue; if (low == low2 && high == high2) { yyerror2("duplicate portcon entry for %s %d-%d ", id, low, high); goto bad; } if (low2 <= low && high2 >= high) { yyerror2("portcon entry for %s %d-%d hidden by earlier " "entry for %d-%d", id, low, high, low2, high2); goto bad; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_PORT] = newc; free(id); return 0; bad: free(id); free(newc); return -1; } int define_ibpkey_context(unsigned int low, unsigned int high) { ocontext_t *newc, *c, *l, *head; struct in6_addr subnet_prefix; char *id; int rc = 0; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("ibpkeycon not supported for target"); return -1; } if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } newc = malloc(sizeof(*newc)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(*newc)); id = queue_remove(id_queue); if (!id) { yyerror("failed to read the subnet prefix"); rc = -1; goto out; } rc = inet_pton(AF_INET6, id, &subnet_prefix); free(id); if (rc < 1) { yyerror("failed to parse the subnet prefix"); if (rc == 0) rc = -1; goto out; } if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) { yyerror("subnet prefix should be 0's in the low order 64 bits."); rc = -1; goto out; } if (low > 0xffff || high > 0xffff) { yyerror("pkey value too large, pkeys are 16 bits."); rc = -1; goto out; } memcpy(&newc->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0], sizeof(newc->u.ibpkey.subnet_prefix)); newc->u.ibpkey.low_pkey = low; newc->u.ibpkey.high_pkey = high; if (low > high) { yyerror2("low pkey %d exceeds high pkey %d", low, high); rc = -1; goto out; } rc = parse_security_context(&newc->context[0]); if (rc) goto out; /* Preserve the matching order specified in the configuration. */ head = policydbp->ocontexts[OCON_IBPKEY]; for (l = NULL, c = head; c; l = c, c = c->next) { unsigned int low2, high2; low2 = c->u.ibpkey.low_pkey; high2 = c->u.ibpkey.high_pkey; if (low == low2 && high == high2 && c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) { yyerror2("duplicate ibpkeycon entry for %d-%d ", low, high); rc = -1; goto out; } if (low2 <= low && high2 >= high && c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) { yyerror2("ibpkeycon entry for %d-%d hidden by earlier entry for %d-%d", low, high, low2, high2); rc = -1; goto out; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_IBPKEY] = newc; return 0; out: free(newc); return rc; } int define_ibendport_context(unsigned int port) { ocontext_t *newc, *c, *l, *head; char *id; int rc = 0; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("ibendportcon not supported for target"); return -1; } if (pass == 1) { id = (char *)queue_remove(id_queue); free(id); parse_security_context(NULL); return 0; } if (port > 0xff || port == 0) { yyerror("Invalid ibendport port number, should be 0 < port < 256"); return -1; } newc = malloc(sizeof(*newc)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(*newc)); newc->u.ibendport.dev_name = queue_remove(id_queue); if (!newc->u.ibendport.dev_name) { yyerror("failed to read infiniband device name."); rc = -1; goto out; } if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) { yyerror("infiniband device name exceeds max length of 63."); rc = -1; goto out; } newc->u.ibendport.port = port; if (parse_security_context(&newc->context[0])) { free(newc); return -1; } /* Preserve the matching order specified in the configuration. */ head = policydbp->ocontexts[OCON_IBENDPORT]; for (l = NULL, c = head; c; l = c, c = c->next) { unsigned int port2; port2 = c->u.ibendport.port; if (port == port2 && !strcmp(c->u.ibendport.dev_name, newc->u.ibendport.dev_name)) { yyerror2("duplicate ibendportcon entry for %s port %u", newc->u.ibendport.dev_name, port); rc = -1; goto out; } } if (l) l->next = newc; else policydbp->ocontexts[OCON_IBENDPORT] = newc; return 0; out: free(newc->u.ibendport.dev_name); free(newc); return rc; } int define_netif_context(void) { ocontext_t *newc, *c, *head; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("netifcon not supported for target"); return -1; } if (pass == 1) { free(queue_remove(id_queue)); parse_security_context(NULL); parse_security_context(NULL); return 0; } newc = (ocontext_t *) malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = (char *)queue_remove(id_queue); if (!newc->u.name) { free(newc); return -1; } if (parse_security_context(&newc->context[0])) { free(newc->u.name); free(newc); return -1; } if (parse_security_context(&newc->context[1])) { context_destroy(&newc->context[0]); free(newc->u.name); free(newc); return -1; } head = policydbp->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(newc->u.name, c->u.name)) { yyerror2("duplicate entry for network interface %s", newc->u.name); context_destroy(&newc->context[0]); context_destroy(&newc->context[1]); free(newc->u.name); free(newc); return -1; } } newc->next = head; policydbp->ocontexts[OCON_NETIF] = newc; return 0; } int define_ipv4_node_context() { char *id; int rc = 0; struct in_addr addr, mask; ocontext_t *newc, *c, *l, *head; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("nodecon not supported for target"); return -1; } if (pass == 1) { free(queue_remove(id_queue)); free(queue_remove(id_queue)); parse_security_context(NULL); goto out; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv4 address"); rc = -1; goto out; } rc = inet_pton(AF_INET, id, &addr); free(id); if (rc < 1) { yyerror("failed to parse ipv4 address"); if (rc == 0) rc = -1; goto out; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv4 address"); rc = -1; goto out; } rc = inet_pton(AF_INET, id, &mask); free(id); if (rc < 1) { yyerror("failed to parse ipv4 mask"); if (rc == 0) rc = -1; goto out; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); rc = -1; goto out; } memset(newc, 0, sizeof(ocontext_t)); newc->u.node.addr = addr.s_addr; newc->u.node.mask = mask.s_addr; if (parse_security_context(&newc->context[0])) { free(newc); return -1; } /* Create order of most specific to least retaining the order specified in the configuration. */ head = policydbp->ocontexts[OCON_NODE]; for (l = NULL, c = head; c; l = c, c = c->next) { if (newc->u.node.mask > c->u.node.mask) break; } newc->next = c; if (l) l->next = newc; else policydbp->ocontexts[OCON_NODE] = newc; rc = 0; out: return rc; } int define_ipv6_node_context(void) { char *id; int rc = 0; struct in6_addr addr, mask; ocontext_t *newc, *c, *l, *head; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("nodecon not supported for target"); return -1; } if (pass == 1) { free(queue_remove(id_queue)); free(queue_remove(id_queue)); parse_security_context(NULL); goto out; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv6 address"); rc = -1; goto out; } rc = inet_pton(AF_INET6, id, &addr); free(id); if (rc < 1) { yyerror("failed to parse ipv6 address"); if (rc == 0) rc = -1; goto out; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv6 address"); rc = -1; goto out; } rc = inet_pton(AF_INET6, id, &mask); free(id); if (rc < 1) { yyerror("failed to parse ipv6 mask"); if (rc == 0) rc = -1; goto out; } newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); rc = -1; goto out; } memset(newc, 0, sizeof(ocontext_t)); memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16); memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16); if (parse_security_context(&newc->context[0])) { free(newc); rc = -1; goto out; } /* Create order of most specific to least retaining the order specified in the configuration. */ head = policydbp->ocontexts[OCON_NODE6]; for (l = NULL, c = head; c; l = c, c = c->next) { if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0) break; } newc->next = c; if (l) l->next = newc; else policydbp->ocontexts[OCON_NODE6] = newc; rc = 0; out: return rc; } int define_fs_use(int behavior) { ocontext_t *newc, *c, *head; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("fsuse not supported for target"); return -1; } if (pass == 1) { free(queue_remove(id_queue)); parse_security_context(NULL); return 0; } newc = (ocontext_t *) malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = (char *)queue_remove(id_queue); if (!newc->u.name) { free(newc); return -1; } newc->v.behavior = behavior; if (parse_security_context(&newc->context[0])) { free(newc->u.name); free(newc); return -1; } head = policydbp->ocontexts[OCON_FSUSE]; for (c = head; c; c = c->next) { if (!strcmp(newc->u.name, c->u.name)) { yyerror2("duplicate fs_use entry for filesystem type %s", newc->u.name); context_destroy(&newc->context[0]); free(newc->u.name); free(newc); return -1; } } newc->next = head; policydbp->ocontexts[OCON_FSUSE] = newc; return 0; } int define_genfs_context_helper(char *fstype, int has_type) { struct genfs *genfs_p, *genfs, *newgenfs; ocontext_t *newc, *c, *head, *p; char *type = NULL; int len, len2; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("genfs not supported for target"); return -1; } if (pass == 1) { free(fstype); free(queue_remove(id_queue)); if (has_type) free(queue_remove(id_queue)); parse_security_context(NULL); return 0; } for (genfs_p = NULL, genfs = policydbp->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { if (strcmp(fstype, genfs->fstype) <= 0) break; } if (!genfs || strcmp(fstype, genfs->fstype)) { newgenfs = malloc(sizeof(struct genfs)); if (!newgenfs) { yyerror("out of memory"); return -1; } memset(newgenfs, 0, sizeof(struct genfs)); newgenfs->fstype = fstype; newgenfs->next = genfs; if (genfs_p) genfs_p->next = newgenfs; else policydbp->genfs = newgenfs; genfs = newgenfs; } else { free(fstype); fstype = NULL; } newc = (ocontext_t *) malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = (char *)queue_remove(id_queue); if (!newc->u.name) goto fail; if (has_type) { type = (char *)queue_remove(id_queue); if (!type) goto fail; if (type[1] != 0) { yyerror2("invalid type %s", type); goto fail; } switch (type[0]) { case 'b': newc->v.sclass = SECCLASS_BLK_FILE; break; case 'c': newc->v.sclass = SECCLASS_CHR_FILE; break; case 'd': newc->v.sclass = SECCLASS_DIR; break; case 'p': newc->v.sclass = SECCLASS_FIFO_FILE; break; case 'l': newc->v.sclass = SECCLASS_LNK_FILE; break; case 's': newc->v.sclass = SECCLASS_SOCK_FILE; break; case '-': newc->v.sclass = SECCLASS_FILE; break; default: yyerror2("invalid type %s", type); goto fail; } } if (parse_security_context(&newc->context[0])) goto fail; head = genfs->head; for (p = NULL, c = head; c; p = c, c = c->next) { if (!strcmp(newc->u.name, c->u.name) && (!newc->v.sclass || !c->v.sclass || newc->v.sclass == c->v.sclass)) { yyerror2("duplicate entry for genfs entry (%s, %s)", genfs->fstype, newc->u.name); goto fail; } len = strlen(newc->u.name); len2 = strlen(c->u.name); if (len > len2) break; } newc->next = c; if (p) p->next = newc; else genfs->head = newc; free(type); return 0; fail: if (type) free(type); context_destroy(&newc->context[0]); if (fstype) free(fstype); if (newc->u.name) free(newc->u.name); free(newc); return -1; } int define_genfs_context(int has_type) { return define_genfs_context_helper(queue_remove(id_queue), has_type); } int define_range_trans(int class_specified) { char *id; level_datum_t *levdatum = 0; class_datum_t *cladatum; range_trans_rule_t *rule; int l, add = 1; if (!mlspol) { yyerror("range_transition rule in non-MLS configuration"); return -1; } if (pass == 1) { while ((id = queue_remove(id_queue))) free(id); while ((id = queue_remove(id_queue))) free(id); if (class_specified) while ((id = queue_remove(id_queue))) free(id); id = queue_remove(id_queue); free(id); for (l = 0; l < 2; l++) { while ((id = queue_remove(id_queue))) { free(id); } id = queue_remove(id_queue); if (!id) break; free(id); } return 0; } rule = malloc(sizeof(struct range_trans_rule)); if (!rule) { yyerror("out of memory"); return -1; } range_trans_rule_init(rule); while ((id = queue_remove(id_queue))) { if (set_types(&rule->stypes, id, &add, 0)) goto out; } add = 1; while ((id = queue_remove(id_queue))) { if (set_types(&rule->ttypes, id, &add, 0)) goto out; } if (class_specified) { if (read_classes(&rule->tclasses)) goto out; } else { cladatum = hashtab_search(policydbp->p_classes.table, "process"); if (!cladatum) { yyerror2("could not find process class for " "legacy range_transition statement"); goto out; } if (ebitmap_set_bit(&rule->tclasses, cladatum->s.value - 1, TRUE)) { yyerror("out of memory"); goto out; } } id = (char *)queue_remove(id_queue); if (!id) { yyerror("no range in range_transition definition?"); goto out; } for (l = 0; l < 2; l++) { levdatum = hashtab_search(policydbp->p_levels.table, id); if (!levdatum) { yyerror2("unknown level %s used in range_transition " "definition", id); free(id); goto out; } free(id); rule->trange.level[l].sens = levdatum->level->sens; while ((id = queue_remove(id_queue))) { if (parse_semantic_categories(id, levdatum, &rule->trange.level[l].cat)) { free(id); goto out; } free(id); } id = (char *)queue_remove(id_queue); if (!id) break; } if (l == 0) { if (mls_semantic_level_cpy(&rule->trange.level[1], &rule->trange.level[0])) { yyerror("out of memory"); goto out; } } append_range_trans(rule); return 0; out: range_trans_rule_destroy(rule); free(rule); return -1; } /* FLASK */ checkpolicy/policy_define.h0100644 0000000 0000000 00000005502 13756670063 015103 0ustar000000000 0000000 /* Functions used to define policy grammar components. */ #ifndef _POLICY_DEFINE_H_ #define _POLICY_DEFINE_H_ /* * We need the following so we have a valid error return code in yacc * when we have a parse error for a conditional rule. We can't check * for NULL (ie 0) because that is a potentially valid return. */ #define COND_ERR ((avrule_t *)-1) #define TRUE 1 #define FALSE 0 avrule_t *define_cond_compute_type(int which); avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt); avrule_t *define_cond_te_avtab(int which); avrule_t *define_cond_filename_trans(void); cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2); int define_attrib(void); int define_attrib_role(void); int define_av_perms(int inherits); int define_bool_tunable(int is_tunable); int define_category(void); int define_class(void); int define_default_user(int which); int define_default_role(int which); int define_default_type(int which); int define_default_range(int which); int define_common_perms(void); int define_compute_type(int which); int define_conditional(cond_expr_t *expr, avrule_t *t_list, avrule_t *f_list ); int define_constraint(constraint_expr_t *expr); int define_dominance(void); int define_fs_context(unsigned int major, unsigned int minor); int define_fs_use(int behavior); int define_genfs_context(int has_type); int define_initial_sid_context(void); int define_initial_sid(void); int define_ipv4_node_context(void); int define_ipv6_node_context(void); int define_level(void); int define_netif_context(void); int define_permissive(void); int define_polcap(void); int define_ibpkey_context(unsigned int low, unsigned int high); int define_ibendport_context(unsigned int port); int define_port_context(unsigned int low, unsigned int high); int define_pirq_context(unsigned int pirq); int define_iomem_context(uint64_t low, uint64_t high); int define_ioport_context(unsigned long low, unsigned long high); int define_pcidevice_context(unsigned long device); int define_devicetree_context(void); int define_range_trans(int class_specified); int define_role_allow(void); int define_role_trans(int class_specified); int define_role_types(void); int define_role_attr(void); int define_roleattribute(void); int define_filename_trans(void); int define_sens(void); int define_te_avtab(int which); int define_te_avtab_extended_perms(int which); int define_typealias(void); int define_typeattribute(void); int define_typebounds(void); int define_type(int alias); int define_user(void); int define_validatetrans(constraint_expr_t *expr); int expand_attrib(void); int insert_id(const char *id,int push); int insert_separator(int push); role_datum_t *define_role_dom(role_datum_t *r); role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2); uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2); #endif /* _POLICY_DEFINE_H_ */ checkpolicy/policy_parse.y0100644 0000000 0000000 00000102611 13756670063 015003 0ustar000000000 0000000 /* * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: David Caplan, * * Added conditional policy language extensions * * Updated: Joshua Brindle * Karl MacMillan * Jason Tang * * Added support for binary policy modules * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2008 Tresys Technology, LLC * Copyright (C) 2007 Red Hat Inc. * Copyright (C) 2017 Mellanox Technologies Inc. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* FLASK */ %{ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "queue.h" #include "checkpolicy.h" #include "module_compiler.h" #include "policy_define.h" extern policydb_t *policydbp; extern unsigned int pass; extern char yytext[]; extern int yylex(void); extern int yywarn(const char *msg); extern int yyerror(const char *msg); typedef int (* require_func_t)(int pass); %} %union { unsigned int val; uint64_t val64; uintptr_t valptr; void *ptr; require_func_t require_func; } %type cond_expr cond_expr_prim cond_pol_list cond_else %type cond_allow_def cond_auditallow_def cond_auditdeny_def cond_dontaudit_def %type cond_transition_def cond_te_avtab_def cond_rule_def %type role_def roles %type cexpr cexpr_prim op role_mls_op %type ipv4_addr_def number %type number64 %type require_decl_def %token PATH %token QPATH %token FILENAME %token CLONE %token COMMON %token CLASS %token CONSTRAIN %token VALIDATETRANS %token INHERITS %token SID %token ROLE %token ROLEATTRIBUTE %token ATTRIBUTE_ROLE %token ROLES %token TYPEALIAS %token TYPEATTRIBUTE %token TYPEBOUNDS %token TYPE %token TYPES %token ALIAS %token ATTRIBUTE %token EXPANDATTRIBUTE %token BOOL %token TUNABLE %token IF %token ELSE %token TYPE_TRANSITION %token TYPE_MEMBER %token TYPE_CHANGE %token ROLE_TRANSITION %token RANGE_TRANSITION %token SENSITIVITY %token DOMINANCE %token DOM DOMBY INCOMP %token CATEGORY %token LEVEL %token RANGE %token MLSCONSTRAIN %token MLSVALIDATETRANS %token USER %token NEVERALLOW %token ALLOW %token AUDITALLOW %token AUDITDENY %token DONTAUDIT %token ALLOWXPERM %token AUDITALLOWXPERM %token DONTAUDITXPERM %token NEVERALLOWXPERM %token SOURCE %token TARGET %token SAMEUSER %token FSCON PORTCON NETIFCON NODECON %token IBPKEYCON %token IBENDPORTCON %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON %token FSUSEXATTR FSUSETASK FSUSETRANS %token GENFSCON %token U1 U2 U3 R1 R2 R3 T1 T2 T3 L1 L2 H1 H2 %token NOT AND OR XOR %token CTRUE CFALSE %token IDENTIFIER %token NUMBER %token EQUALS %token NOTEQUAL %token IPV4_ADDR %token IPV6_ADDR %token MODULE VERSION_IDENTIFIER REQUIRE OPTIONAL %token POLICYCAP %token PERMISSIVE %token FILESYSTEM %token DEFAULT_USER DEFAULT_ROLE DEFAULT_TYPE DEFAULT_RANGE %token LOW_HIGH LOW HIGH %left OR %left XOR %left AND %right NOT %left EQUALS NOTEQUAL %% policy : base_policy | module_policy ; base_policy : { if (define_policy(pass, 0) == -1) return -1; } classes initial_sids access_vectors { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; } else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1; }} opt_default_rules opt_mls te_rbac users opt_constraints { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;} else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}} initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts opt_ibendport_contexts ; classes : class_def | classes class_def ; class_def : CLASS identifier {if (define_class()) return -1;} ; initial_sids : initial_sid_def | initial_sids initial_sid_def ; initial_sid_def : SID identifier {if (define_initial_sid()) return -1;} ; access_vectors : opt_common_perms av_perms ; opt_common_perms : common_perms | ; common_perms : common_perms_def | common_perms common_perms_def ; common_perms_def : COMMON identifier '{' identifier_list '}' {if (define_common_perms()) return -1;} ; av_perms : av_perms_def | av_perms av_perms_def ; av_perms_def : CLASS identifier '{' identifier_list '}' {if (define_av_perms(FALSE)) return -1;} | CLASS identifier INHERITS identifier {if (define_av_perms(TRUE)) return -1;} | CLASS identifier INHERITS identifier '{' identifier_list '}' {if (define_av_perms(TRUE)) return -1;} ; opt_default_rules : default_rules | ; default_rules : default_user_def | default_role_def | default_type_def | default_range_def | default_rules default_user_def | default_rules default_role_def | default_rules default_type_def | default_rules default_range_def ; default_user_def : DEFAULT_USER names SOURCE ';' {if (define_default_user(DEFAULT_SOURCE)) return -1; } | DEFAULT_USER names TARGET ';' {if (define_default_user(DEFAULT_TARGET)) return -1; } ; default_role_def : DEFAULT_ROLE names SOURCE ';' {if (define_default_role(DEFAULT_SOURCE)) return -1; } | DEFAULT_ROLE names TARGET ';' {if (define_default_role(DEFAULT_TARGET)) return -1; } ; default_type_def : DEFAULT_TYPE names SOURCE ';' {if (define_default_type(DEFAULT_SOURCE)) return -1; } | DEFAULT_TYPE names TARGET ';' {if (define_default_type(DEFAULT_TARGET)) return -1; } ; default_range_def : DEFAULT_RANGE names SOURCE LOW ';' {if (define_default_range(DEFAULT_SOURCE_LOW)) return -1; } | DEFAULT_RANGE names SOURCE HIGH ';' {if (define_default_range(DEFAULT_SOURCE_HIGH)) return -1; } | DEFAULT_RANGE names SOURCE LOW_HIGH ';' {if (define_default_range(DEFAULT_SOURCE_LOW_HIGH)) return -1; } | DEFAULT_RANGE names TARGET LOW ';' {if (define_default_range(DEFAULT_TARGET_LOW)) return -1; } | DEFAULT_RANGE names TARGET HIGH ';' {if (define_default_range(DEFAULT_TARGET_HIGH)) return -1; } | DEFAULT_RANGE names TARGET LOW_HIGH ';' {if (define_default_range(DEFAULT_TARGET_LOW_HIGH)) return -1; } ; opt_mls : mls | ; mls : sensitivities dominance opt_categories levels mlspolicy ; sensitivities : sensitivity_def | sensitivities sensitivity_def ; sensitivity_def : SENSITIVITY identifier alias_def ';' {if (define_sens()) return -1;} | SENSITIVITY identifier ';' {if (define_sens()) return -1;} ; alias_def : ALIAS names ; dominance : DOMINANCE identifier {if (define_dominance()) return -1;} | DOMINANCE '{' identifier_list '}' {if (define_dominance()) return -1;} ; opt_categories : categories | ; categories : category_def | categories category_def ; category_def : CATEGORY identifier alias_def ';' {if (define_category()) return -1;} | CATEGORY identifier ';' {if (define_category()) return -1;} ; levels : level_def | levels level_def ; level_def : LEVEL identifier ':' id_comma_list ';' {if (define_level()) return -1;} | LEVEL identifier ';' {if (define_level()) return -1;} ; mlspolicy : mlspolicy_decl | mlspolicy mlspolicy_decl ; mlspolicy_decl : mlsconstraint_def | mlsvalidatetrans_def ; mlsconstraint_def : MLSCONSTRAIN names names cexpr ';' { if (define_constraint((constraint_expr_t*)$4)) return -1; } ; mlsvalidatetrans_def : MLSVALIDATETRANS names cexpr ';' { if (define_validatetrans((constraint_expr_t*)$3)) return -1; } ; te_rbac : te_rbac_decl | te_rbac te_rbac_decl ; te_rbac_decl : te_decl | rbac_decl | cond_stmt_def | optional_block | policycap_def | ';' ; rbac_decl : attribute_role_def | role_type_def | role_dominance | role_trans_def | role_allow_def | roleattribute_def | role_attr_def ; te_decl : attribute_def | expandattribute_def | type_def | typealias_def | typeattribute_def | typebounds_def | bool_def | tunable_def | transition_def | range_trans_def | te_avtab_def | permissive_def ; attribute_def : ATTRIBUTE identifier ';' { if (define_attrib()) return -1;} ; expandattribute_def : EXPANDATTRIBUTE names bool_val ';' { if (expand_attrib()) return -1;} ; type_def : TYPE identifier alias_def opt_attr_list ';' {if (define_type(1)) return -1;} | TYPE identifier opt_attr_list ';' {if (define_type(0)) return -1;} ; typealias_def : TYPEALIAS identifier alias_def ';' {if (define_typealias()) return -1;} ; typeattribute_def : TYPEATTRIBUTE identifier id_comma_list ';' {if (define_typeattribute()) return -1;} ; typebounds_def : TYPEBOUNDS identifier id_comma_list ';' {if (define_typebounds()) return -1;} ; opt_attr_list : ',' id_comma_list | ; bool_def : BOOL identifier bool_val ';' { if (define_bool_tunable(0)) return -1; } ; tunable_def : TUNABLE identifier bool_val ';' { if (define_bool_tunable(1)) return -1; } ; bool_val : CTRUE { if (insert_id("T",0)) return -1; } | CFALSE { if (insert_id("F",0)) return -1; } ; cond_stmt_def : IF cond_expr '{' cond_pol_list '}' cond_else { if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (avrule_t*)$4, (avrule_t*)$6) < 0) return -1; }} ; cond_else : ELSE '{' cond_pol_list '}' { $$ = $3; } | /* empty */ { $$ = NULL; } ; cond_expr : '(' cond_expr ')' { $$ = $2;} | NOT cond_expr { $$ = define_cond_expr(COND_NOT, $2, 0); if ($$ == 0) return -1; } | cond_expr AND cond_expr { $$ = define_cond_expr(COND_AND, $1, $3); if ($$ == 0) return -1; } | cond_expr OR cond_expr { $$ = define_cond_expr(COND_OR, $1, $3); if ($$ == 0) return -1; } | cond_expr XOR cond_expr { $$ = define_cond_expr(COND_XOR, $1, $3); if ($$ == 0) return -1; } | cond_expr EQUALS cond_expr { $$ = define_cond_expr(COND_EQ, $1, $3); if ($$ == 0) return -1; } | cond_expr NOTEQUAL cond_expr { $$ = define_cond_expr(COND_NEQ, $1, $3); if ($$ == 0) return -1; } | cond_expr_prim { $$ = $1; } ; cond_expr_prim : identifier { $$ = define_cond_expr(COND_BOOL,0, 0); if ($$ == COND_ERR) return -1; } ; cond_pol_list : cond_pol_list cond_rule_def { $$ = define_cond_pol_list((avrule_t *)$1, (avrule_t *)$2); } | /* empty */ { $$ = NULL; } ; cond_rule_def : cond_transition_def { $$ = $1; } | cond_te_avtab_def { $$ = $1; } | require_block { $$ = NULL; } ; cond_transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' { $$ = define_cond_filename_trans() ; if ($$ == COND_ERR) return -1;} | TYPE_TRANSITION names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_TRANSITION) ; if ($$ == COND_ERR) return -1;} | TYPE_MEMBER names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_MEMBER) ; if ($$ == COND_ERR) return -1;} | TYPE_CHANGE names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_CHANGE) ; if ($$ == COND_ERR) return -1;} ; cond_te_avtab_def : cond_allow_def { $$ = $1; } | cond_auditallow_def { $$ = $1; } | cond_auditdeny_def { $$ = $1; } | cond_dontaudit_def { $$ = $1; } ; cond_allow_def : ALLOW names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_ALLOWED) ; if ($$ == COND_ERR) return -1; } ; cond_auditallow_def : AUDITALLOW names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_AUDITALLOW) ; if ($$ == COND_ERR) return -1; } ; cond_auditdeny_def : AUDITDENY names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_AUDITDENY) ; if ($$ == COND_ERR) return -1; } ; cond_dontaudit_def : DONTAUDIT names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_DONTAUDIT); if ($$ == COND_ERR) return -1; } ; ; transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' {if (define_filename_trans()) return -1; } | TYPE_TRANSITION names names ':' names identifier ';' {if (define_compute_type(AVRULE_TRANSITION)) return -1;} | TYPE_MEMBER names names ':' names identifier ';' {if (define_compute_type(AVRULE_MEMBER)) return -1;} | TYPE_CHANGE names names ':' names identifier ';' {if (define_compute_type(AVRULE_CHANGE)) return -1;} ; range_trans_def : RANGE_TRANSITION names names mls_range_def ';' { if (define_range_trans(0)) return -1; } | RANGE_TRANSITION names names ':' names mls_range_def ';' { if (define_range_trans(1)) return -1; } ; te_avtab_def : allow_def | auditallow_def | auditdeny_def | dontaudit_def | neverallow_def | xperm_allow_def | xperm_auditallow_def | xperm_dontaudit_def | xperm_neverallow_def ; allow_def : ALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_ALLOWED)) return -1; } ; auditallow_def : AUDITALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_AUDITALLOW)) return -1; } ; auditdeny_def : AUDITDENY names names ':' names names ';' {if (define_te_avtab(AVRULE_AUDITDENY)) return -1; } ; dontaudit_def : DONTAUDIT names names ':' names names ';' {if (define_te_avtab(AVRULE_DONTAUDIT)) return -1; } ; neverallow_def : NEVERALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; } ; xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';' {if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) return -1; } ; xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';' {if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) return -1; } ; xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';' {if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; } ; xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';' {if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; } ; attribute_role_def : ATTRIBUTE_ROLE identifier ';' {if (define_attrib_role()) return -1; } ; role_type_def : ROLE identifier TYPES names ';' {if (define_role_types()) return -1;} ; role_attr_def : ROLE identifier opt_attr_list ';' {if (define_role_attr()) return -1;} ; role_dominance : DOMINANCE '{' roles '}' ; role_trans_def : ROLE_TRANSITION names names identifier ';' {if (define_role_trans(0)) return -1; } | ROLE_TRANSITION names names ':' names identifier ';' {if (define_role_trans(1)) return -1;} ; role_allow_def : ALLOW names names ';' {if (define_role_allow()) return -1; } ; roles : role_def { $$ = $1; } | roles role_def { $$ = merge_roles_dom((role_datum_t*)$1, (role_datum_t*)$2); if ($$ == 0) return -1;} ; role_def : ROLE identifier_push ';' {$$ = define_role_dom(NULL); if ($$ == 0) return -1;} | ROLE identifier_push '{' roles '}' {$$ = define_role_dom((role_datum_t*)$4); if ($$ == 0) return -1;} ; roleattribute_def : ROLEATTRIBUTE identifier id_comma_list ';' {if (define_roleattribute()) return -1;} ; opt_constraints : constraints | ; constraints : constraint_decl | constraints constraint_decl ; constraint_decl : constraint_def | validatetrans_def ; constraint_def : CONSTRAIN names names cexpr ';' { if (define_constraint((constraint_expr_t*)$4)) return -1; } ; validatetrans_def : VALIDATETRANS names cexpr ';' { if (define_validatetrans((constraint_expr_t*)$3)) return -1; } ; cexpr : '(' cexpr ')' { $$ = $2; } | NOT cexpr { $$ = define_cexpr(CEXPR_NOT, $2, 0); if ($$ == 0) return -1; } | cexpr AND cexpr { $$ = define_cexpr(CEXPR_AND, $1, $3); if ($$ == 0) return -1; } | cexpr OR cexpr { $$ = define_cexpr(CEXPR_OR, $1, $3); if ($$ == 0) return -1; } | cexpr_prim { $$ = $1; } ; cexpr_prim : U1 op U2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, $2); if ($$ == 0) return -1; } | R1 role_mls_op R2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); if ($$ == 0) return -1; } | T1 op T2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_TYPE, $2); if ($$ == 0) return -1; } | U1 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_USER, $2); if ($$ == 0) return -1; } | U2 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_TARGET), $2); if ($$ == 0) return -1; } | U3 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_XTARGET), $2); if ($$ == 0) return -1; } | R1 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, $2); if ($$ == 0) return -1; } | R2 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), $2); if ($$ == 0) return -1; } | R3 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_XTARGET), $2); if ($$ == 0) return -1; } | T1 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, $2); if ($$ == 0) return -1; } | T2 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), $2); if ($$ == 0) return -1; } | T3 op { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_XTARGET), $2); if ($$ == 0) return -1; } | SAMEUSER { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, CEXPR_EQ); if ($$ == 0) return -1; } | SOURCE ROLE { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, CEXPR_EQ); if ($$ == 0) return -1; } | TARGET ROLE { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), CEXPR_EQ); if ($$ == 0) return -1; } | ROLE role_mls_op { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); if ($$ == 0) return -1; } | SOURCE TYPE { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, CEXPR_EQ); if ($$ == 0) return -1; } | TARGET TYPE { if (insert_separator(1)) return -1; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), CEXPR_EQ); if ($$ == 0) return -1; } | L1 role_mls_op L2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1L2, $2); if ($$ == 0) return -1; } | L1 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H2, $2); if ($$ == 0) return -1; } | H1 role_mls_op L2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1L2, $2); if ($$ == 0) return -1; } | H1 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1H2, $2); if ($$ == 0) return -1; } | L1 role_mls_op H1 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H1, $2); if ($$ == 0) return -1; } | L2 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L2H2, $2); if ($$ == 0) return -1; } ; op : EQUALS { $$ = CEXPR_EQ; } | NOTEQUAL { $$ = CEXPR_NEQ; } ; role_mls_op : op { $$ = $1; } | DOM { $$ = CEXPR_DOM; } | DOMBY { $$ = CEXPR_DOMBY; } | INCOMP { $$ = CEXPR_INCOMP; } ; users : user_def | users user_def ; user_def : USER identifier ROLES names opt_mls_user ';' {if (define_user()) return -1;} ; opt_mls_user : LEVEL mls_level_def RANGE mls_range_def | ; initial_sid_contexts : initial_sid_context_def | initial_sid_contexts initial_sid_context_def ; initial_sid_context_def : SID identifier security_context_def {if (define_initial_sid_context()) return -1;} ; opt_dev_contexts : dev_contexts | ; dev_contexts : dev_context_def | dev_contexts dev_context_def ; dev_context_def : pirq_context_def | iomem_context_def | ioport_context_def | pci_context_def | dtree_context_def ; pirq_context_def : PIRQCON number security_context_def {if (define_pirq_context($2)) return -1;} ; iomem_context_def : IOMEMCON number64 security_context_def {if (define_iomem_context($2,$2)) return -1;} | IOMEMCON number64 '-' number64 security_context_def {if (define_iomem_context($2,$4)) return -1;} ; ioport_context_def : IOPORTCON number security_context_def {if (define_ioport_context($2,$2)) return -1;} | IOPORTCON number '-' number security_context_def {if (define_ioport_context($2,$4)) return -1;} ; pci_context_def : PCIDEVICECON number security_context_def {if (define_pcidevice_context($2)) return -1;} ; dtree_context_def : DEVICETREECON path security_context_def {if (define_devicetree_context()) return -1;} ; opt_fs_contexts : fs_contexts | ; fs_contexts : fs_context_def | fs_contexts fs_context_def ; fs_context_def : FSCON number number security_context_def security_context_def {if (define_fs_context($2,$3)) return -1;} ; net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts ; opt_port_contexts : port_contexts | ; port_contexts : port_context_def | port_contexts port_context_def ; port_context_def : PORTCON identifier number security_context_def {if (define_port_context($3,$3)) return -1;} | PORTCON identifier number '-' number security_context_def {if (define_port_context($3,$5)) return -1;} ; opt_ibpkey_contexts : ibpkey_contexts | ; ibpkey_contexts : ibpkey_context_def | ibpkey_contexts ibpkey_context_def ; ibpkey_context_def : IBPKEYCON ipv6_addr number security_context_def {if (define_ibpkey_context($3,$3)) return -1;} | IBPKEYCON ipv6_addr number '-' number security_context_def {if (define_ibpkey_context($3,$5)) return -1;} ; opt_ibendport_contexts : ibendport_contexts | ; ibendport_contexts : ibendport_context_def | ibendport_contexts ibendport_context_def ; ibendport_context_def : IBENDPORTCON identifier number security_context_def {if (define_ibendport_context($3)) return -1;} ; opt_netif_contexts : netif_contexts | ; netif_contexts : netif_context_def | netif_contexts netif_context_def ; netif_context_def : NETIFCON identifier security_context_def security_context_def {if (define_netif_context()) return -1;} ; opt_node_contexts : node_contexts | ; node_contexts : node_context_def | node_contexts node_context_def ; node_context_def : NODECON ipv4_addr_def ipv4_addr_def security_context_def {if (define_ipv4_node_context()) return -1;} | NODECON ipv6_addr ipv6_addr security_context_def {if (define_ipv6_node_context()) return -1;} ; opt_fs_uses : fs_uses | ; fs_uses : fs_use_def | fs_uses fs_use_def ; fs_use_def : FSUSEXATTR filesystem security_context_def ';' {if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;} | FSUSETASK identifier security_context_def ';' {if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;} | FSUSETRANS identifier security_context_def ';' {if (define_fs_use(SECURITY_FS_USE_TRANS)) return -1;} ; opt_genfs_contexts : genfs_contexts | ; genfs_contexts : genfs_context_def | genfs_contexts genfs_context_def ; genfs_context_def : GENFSCON filesystem path '-' identifier security_context_def {if (define_genfs_context(1)) return -1;} | GENFSCON filesystem path '-' '-' {insert_id("-", 0);} security_context_def {if (define_genfs_context(1)) return -1;} | GENFSCON filesystem path security_context_def {if (define_genfs_context(0)) return -1;} ; ipv4_addr_def : IPV4_ADDR { if (insert_id(yytext,0)) return -1; } ; xperms : xperm { if (insert_separator(0)) return -1; } | nested_xperm_set { if (insert_separator(0)) return -1; } | tilde xperm { if (insert_id("~", 0)) return -1; } | tilde nested_xperm_set { if (insert_id("~", 0)) return -1; if (insert_separator(0)) return -1; } ; nested_xperm_set : '{' nested_xperm_list '}' ; nested_xperm_list : nested_xperm_element | nested_xperm_list nested_xperm_element ; nested_xperm_element: xperm '-' { if (insert_id("-", 0)) return -1; } xperm | xperm | nested_xperm_set ; xperm : number { if (insert_id(yytext,0)) return -1; } ; security_context_def : identifier ':' identifier ':' identifier opt_mls_range_def ; opt_mls_range_def : ':' mls_range_def | ; mls_range_def : mls_level_def '-' mls_level_def {if (insert_separator(0)) return -1;} | mls_level_def {if (insert_separator(0)) return -1;} ; mls_level_def : identifier ':' id_comma_list {if (insert_separator(0)) return -1;} | identifier {if (insert_separator(0)) return -1;} ; id_comma_list : identifier | id_comma_list ',' identifier ; tilde : '~' ; asterisk : '*' ; names : identifier { if (insert_separator(0)) return -1; } | nested_id_set { if (insert_separator(0)) return -1; } | asterisk { if (insert_id("*", 0)) return -1; if (insert_separator(0)) return -1; } | tilde identifier { if (insert_id("~", 0)) return -1; if (insert_separator(0)) return -1; } | tilde nested_id_set { if (insert_id("~", 0)) return -1; if (insert_separator(0)) return -1; } | identifier '-' { if (insert_id("-", 0)) return -1; } identifier { if (insert_separator(0)) return -1; } ; tilde_push : tilde { if (insert_id("~", 1)) return -1; } ; asterisk_push : asterisk { if (insert_id("*", 1)) return -1; } ; names_push : identifier_push | '{' identifier_list_push '}' | asterisk_push | tilde_push identifier_push | tilde_push '{' identifier_list_push '}' ; identifier_list_push : identifier_push | identifier_list_push identifier_push ; identifier_push : IDENTIFIER { if (insert_id(yytext, 1)) return -1; } ; identifier_list : identifier | identifier_list identifier ; nested_id_set : '{' nested_id_list '}' ; nested_id_list : nested_id_element | nested_id_list nested_id_element ; nested_id_element : identifier | '-' { if (insert_id("-", 0)) return -1; } identifier | nested_id_set ; identifier : IDENTIFIER { if (insert_id(yytext,0)) return -1; } ; filesystem : FILESYSTEM { if (insert_id(yytext,0)) return -1; } | IDENTIFIER { if (insert_id(yytext,0)) return -1; } ; path : PATH { if (insert_id(yytext,0)) return -1; } | QPATH { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } ; filename : FILENAME { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } ; number : NUMBER { $$ = strtoul(yytext,NULL,0); } ; number64 : NUMBER { $$ = strtoull(yytext,NULL,0); } ; ipv6_addr : IPV6_ADDR { if (insert_id(yytext,0)) return -1; } ; policycap_def : POLICYCAP identifier ';' {if (define_polcap()) return -1;} ; permissive_def : PERMISSIVE identifier ';' {if (define_permissive()) return -1;} /*********** module grammar below ***********/ module_policy : module_def avrules_block { if (end_avrule_block(pass) == -1) return -1; if (policydb_index_others(NULL, policydbp, 0)) return -1; } ; module_def : MODULE identifier version_identifier ';' { if (define_policy(pass, 1) == -1) return -1; } ; version_identifier : VERSION_IDENTIFIER { if (insert_id(yytext,0)) return -1; } | number { if (insert_id(yytext,0)) return -1; } | ipv4_addr_def /* version can look like ipv4 address */ ; avrules_block : avrule_decls avrule_user_defs ; avrule_decls : avrule_decls avrule_decl | avrule_decl ; avrule_decl : rbac_decl | te_decl | cond_stmt_def | require_block | optional_block | ';' ; require_block : REQUIRE '{' require_list '}' ; require_list : require_list require_decl | require_decl ; require_decl : require_class ';' | require_decl_def require_id_list ';' ; require_class : CLASS identifier names { if (require_class(pass)) return -1; } ; require_decl_def : ROLE { $$ = require_role; } | TYPE { $$ = require_type; } | ATTRIBUTE { $$ = require_attribute; } | ATTRIBUTE_ROLE { $$ = require_attribute_role; } | USER { $$ = require_user; } | BOOL { $$ = require_bool; } | TUNABLE { $$ = require_tunable; } | SENSITIVITY { $$ = require_sens; } | CATEGORY { $$ = require_cat; } ; require_id_list : identifier { if ($0 (pass)) return -1; } | require_id_list ',' identifier { if ($0 (pass)) return -1; } ; optional_block : optional_decl '{' avrules_block '}' { if (end_avrule_block(pass) == -1) return -1; } optional_else { if (end_optional(pass) == -1) return -1; } ; optional_else : else_decl '{' avrules_block '}' { if (end_avrule_block(pass) == -1) return -1; } | /* empty */ ; optional_decl : OPTIONAL { if (begin_optional(pass) == -1) return -1; } ; else_decl : ELSE { if (begin_optional_else(pass) == -1) return -1; } ; avrule_user_defs : user_def avrule_user_defs | /* empty */ ; checkpolicy/policy_scan.l0100644 0000000 0000000 00000017443 13756670063 014610 0ustar000000000 0000000 /* * Author : Stephen Smalley, */ /* Updated: David Caplan, * * Added conditional policy language extensions * * Jason Tang * * Added support for binary policy modules * * Copyright (C) 2003-5 Tresys Technology, LLC * Copyright (C) 2017 Mellanox Technologies Inc. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* FLASK */ %{ #include #include #include #include typedef int (* require_func_t)(void); #ifdef ANDROID #include "policy_parse.h" #else #include "y.tab.h" #endif static char linebuf[2][255]; static unsigned int lno = 0; int yywarn(const char *msg); void set_source_file(const char *name); char source_file[PATH_MAX]; unsigned long source_lineno = 1; unsigned long policydb_lineno = 1; unsigned int policydb_errors = 0; %} %option noinput nounput noyywrap %array letter [A-Za-z] digit [0-9] alnum [a-zA-Z0-9] hexval [0-9A-Fa-f] %% \n.* { strncpy(linebuf[lno], yytext+1, 255); linebuf[lno][254] = 0; lno = 1 - lno; policydb_lineno++; source_lineno++; yyless(1); } CLONE | clone { return(CLONE); } COMMON | common { return(COMMON); } CLASS | class { return(CLASS); } CONSTRAIN | constrain { return(CONSTRAIN); } VALIDATETRANS | validatetrans { return(VALIDATETRANS); } INHERITS | inherits { return(INHERITS); } SID | sid { return(SID); } ROLE | role { return(ROLE); } ROLES | roles { return(ROLES); } ROLEATTRIBUTE | roleattribute { return(ROLEATTRIBUTE);} ATTRIBUTE_ROLE | attribute_role { return(ATTRIBUTE_ROLE);} TYPES | types { return(TYPES); } TYPEALIAS | typealias { return(TYPEALIAS); } TYPEATTRIBUTE | typeattribute { return(TYPEATTRIBUTE); } TYPEBOUNDS | typebounds { return(TYPEBOUNDS); } TYPE | type { return(TYPE); } BOOL | bool { return(BOOL); } TUNABLE | tunable { return(TUNABLE); } IF | if { return(IF); } ELSE | else { return(ELSE); } ALIAS | alias { return(ALIAS); } ATTRIBUTE | attribute { return(ATTRIBUTE); } EXPANDATTRIBUTE | expandattribute { return(EXPANDATTRIBUTE); } TYPE_TRANSITION | type_transition { return(TYPE_TRANSITION); } TYPE_MEMBER | type_member { return(TYPE_MEMBER); } TYPE_CHANGE | type_change { return(TYPE_CHANGE); } ROLE_TRANSITION | role_transition { return(ROLE_TRANSITION); } RANGE_TRANSITION | range_transition { return(RANGE_TRANSITION); } SENSITIVITY | sensitivity { return(SENSITIVITY); } DOMINANCE | dominance { return(DOMINANCE); } CATEGORY | category { return(CATEGORY); } LEVEL | level { return(LEVEL); } RANGE | range { return(RANGE); } MLSCONSTRAIN | mlsconstrain { return(MLSCONSTRAIN); } MLSVALIDATETRANS | mlsvalidatetrans { return(MLSVALIDATETRANS); } USER | user { return(USER); } NEVERALLOW | neverallow { return(NEVERALLOW); } ALLOW | allow { return(ALLOW); } AUDITALLOW | auditallow { return(AUDITALLOW); } AUDITDENY | auditdeny { return(AUDITDENY); } DONTAUDIT | dontaudit { return(DONTAUDIT); } ALLOWXPERM | allowxperm { return(ALLOWXPERM); } AUDITALLOWXPERM | auditallowxperm { return(AUDITALLOWXPERM); } DONTAUDITXPERM | dontauditxperm { return(DONTAUDITXPERM); } NEVERALLOWXPERM | neverallowxperm { return(NEVERALLOWXPERM); } SOURCE | source { return(SOURCE); } TARGET | target { return(TARGET); } SAMEUSER | sameuser { return(SAMEUSER);} module|MODULE { return(MODULE); } require|REQUIRE { return(REQUIRE); } optional|OPTIONAL { return(OPTIONAL); } OR | or { return(OR);} AND | and { return(AND);} NOT | not { return(NOT);} xor | XOR { return(XOR); } eq | EQ { return(EQUALS);} true | TRUE { return(CTRUE); } false | FALSE { return(CFALSE); } dom | DOM { return(DOM);} domby | DOMBY { return(DOMBY);} INCOMP | incomp { return(INCOMP);} fscon | FSCON { return(FSCON);} ibpkeycon | IBPKEYCON { return(IBPKEYCON);} ibendportcon | IBENDPORTCON { return(IBENDPORTCON);} portcon | PORTCON { return(PORTCON);} netifcon | NETIFCON { return(NETIFCON);} nodecon | NODECON { return(NODECON);} pirqcon | PIRQCON { return(PIRQCON);} iomemcon | IOMEMCON { return(IOMEMCON);} ioportcon | IOPORTCON { return(IOPORTCON);} pcidevicecon | PCIDEVICECON { return(PCIDEVICECON);} devicetreecon | DEVICETREECON { return(DEVICETREECON);} fs_use_xattr | FS_USE_XATTR { return(FSUSEXATTR);} fs_use_task | FS_USE_TASK { return(FSUSETASK);} fs_use_trans | FS_USE_TRANS { return(FSUSETRANS);} genfscon | GENFSCON { return(GENFSCON);} r1 | R1 { return(R1); } r2 | R2 { return(R2); } r3 | R3 { return(R3); } u1 | U1 { return(U1); } u2 | U2 { return(U2); } u3 | U3 { return(U3); } t1 | T1 { return(T1); } t2 | T2 { return(T2); } t3 | T3 { return(T3); } l1 | L1 { return(L1); } l2 | L2 { return(L2); } h1 | H1 { return(H1); } h2 | H2 { return(H2); } policycap | POLICYCAP { return(POLICYCAP); } permissive | PERMISSIVE { return(PERMISSIVE); } default_user | DEFAULT_USER { return(DEFAULT_USER); } default_role | DEFAULT_ROLE { return(DEFAULT_ROLE); } default_type | DEFAULT_TYPE { return(DEFAULT_TYPE); } default_range | DEFAULT_RANGE { return(DEFAULT_RANGE); } low-high | LOW-HIGH { return(LOW_HIGH); } high | HIGH { return(HIGH); } low | LOW { return(LOW); } "/"[^ \n\r\t\f]* { return(PATH); } \""/"[^\"\n]*\" { return(QPATH); } \"[^"/"\"\n]+\" { return(FILENAME); } {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); } {digit}+|0x{hexval}+ { return(NUMBER); } {alnum}*{letter}{alnum}* { return(FILESYSTEM); } {digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); } {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); } {digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); } #line[ ]1[ ]\"[^\n]*\" { set_source_file(yytext+9); } #line[ ]{digit}+ { source_lineno = atoi(yytext+6)-1; } #[^\n]* { /* delete comments */ } [ \t\f]+ { /* delete whitespace */ } "==" { return(EQUALS); } "!=" { return (NOTEQUAL); } "&&" { return (AND); } "||" { return (OR); } "!" { return (NOT); } "^" { return (XOR); } "," | ":" | ";" | "(" | ")" | "{" | "}" | "[" | "-" | "." | "]" | "~" | "*" { return(yytext[0]); } . { yywarn("unrecognized character");} %% int yyerror(const char *msg) { if (source_file[0]) fprintf(stderr, "%s:%ld:", source_file, source_lineno); else fprintf(stderr, "(unknown source)::"); fprintf(stderr, "ERROR '%s' at token '%s' on line %ld:\n%s\n%s\n", msg, yytext, policydb_lineno, linebuf[0], linebuf[1]); policydb_errors++; return -1; } int yywarn(const char *msg) { if (source_file[0]) fprintf(stderr, "%s:%ld:", source_file, source_lineno); else fprintf(stderr, "(unknown source)::"); fprintf(stderr, "WARNING '%s' at token '%s' on line %ld:\n%s\n%s\n", msg, yytext, policydb_lineno, linebuf[0], linebuf[1]); return 0; } void set_source_file(const char *name) { source_lineno = 1; strncpy(source_file, name, sizeof(source_file)-1); source_file[sizeof(source_file)-1] = '\0'; if (strlen(source_file) && source_file[strlen(source_file)-1] == '"') source_file[strlen(source_file)-1] = '\0'; } checkpolicy/queue.c0100644 0000000 0000000 00000004777 13756670063 013426 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the double-ended queue type. */ #include #include "queue.h" queue_t queue_create(void) { queue_t q; q = (queue_t) malloc(sizeof(struct queue_info)); if (q == NULL) return NULL; q->head = q->tail = NULL; return q; } int queue_insert(queue_t q, queue_element_t e) { queue_node_ptr_t newnode; if (!q) return -1; newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node)); if (newnode == NULL) return -1; newnode->element = e; newnode->next = NULL; if (q->head == NULL) { q->head = q->tail = newnode; } else { q->tail->next = newnode; q->tail = newnode; } return 0; } int queue_push(queue_t q, queue_element_t e) { queue_node_ptr_t newnode; if (!q) return -1; newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node)); if (newnode == NULL) return -1; newnode->element = e; newnode->next = NULL; if (q->head == NULL) { q->head = q->tail = newnode; } else { newnode->next = q->head; q->head = newnode; } return 0; } queue_element_t queue_remove(queue_t q) { queue_node_ptr_t node; queue_element_t e; if (!q) return NULL; if (q->head == NULL) return NULL; node = q->head; q->head = q->head->next; if (q->head == NULL) q->tail = NULL; e = node->element; free(node); return e; } queue_element_t queue_head(queue_t q) { if (!q) return NULL; if (q->head == NULL) return NULL; return q->head->element; } void queue_destroy(queue_t q) { queue_node_ptr_t p, temp; if (!q) return; p = q->head; while (p != NULL) { free(p->element); temp = p; p = p->next; free(temp); } free(q); } int queue_map(queue_t q, int (*f) (queue_element_t, void *), void *vp) { queue_node_ptr_t p; int ret; if (!q) return 0; p = q->head; while (p != NULL) { ret = f(p->element, vp); if (ret) return ret; p = p->next; } return 0; } void queue_map_remove_on_error(queue_t q, int (*f) (queue_element_t, void *), void (*g) (queue_element_t, void *), void *vp) { queue_node_ptr_t p, last, temp; int ret; if (!q) return; last = NULL; p = q->head; while (p != NULL) { ret = f(p->element, vp); if (ret) { if (last) { last->next = p->next; if (last->next == NULL) q->tail = last; } else { q->head = p->next; if (q->head == NULL) q->tail = NULL; } temp = p; p = p->next; g(temp->element, vp); free(temp); } else { last = p; p = p->next; } } return; } /* FLASK */ checkpolicy/queue.h0100644 0000000 0000000 00000002761 13756670063 013422 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A double-ended queue is a singly linked list of * elements of arbitrary type that may be accessed * at either end. */ #ifndef _QUEUE_H_ #define _QUEUE_H_ typedef void *queue_element_t; typedef struct queue_node *queue_node_ptr_t; typedef struct queue_node { queue_element_t element; queue_node_ptr_t next; } queue_node_t; typedef struct queue_info { queue_node_ptr_t head; queue_node_ptr_t tail; } queue_info_t; typedef queue_info_t *queue_t; queue_t queue_create(void); int queue_insert(queue_t, queue_element_t); int queue_push(queue_t, queue_element_t); queue_element_t queue_remove(queue_t); queue_element_t queue_head(queue_t); void queue_destroy(queue_t); /* Applies the specified function f to each element in the specified queue. In addition to passing the element to f, queue_map passes the specified void* pointer to f on each invocation. If f returns a non-zero status, then queue_map will cease iterating through the hash table and will propagate the error return to its caller. */ int queue_map(queue_t, int (*f) (queue_element_t, void *), void *); /* Same as queue_map, except that if f returns a non-zero status, then the element will be removed from the queue and the g function will be applied to the element. */ void queue_map_remove_on_error(queue_t, int (*f) (queue_element_t, void *), void (*g) (queue_element_t, void *), void *); #endif /* FLASK */ checkpolicy/ru/0040755 0000000 0000000 00000000000 13756670063 012550 5ustar000000000 0000000 checkpolicy/ru/checkmodule.80100644 0000000 0000000 00000010033 13756670063 015116 0ustar000000000 0000000 .TH CHECKMODULE 8 .SH ИМЯ checkmodule \- компилятор модулей политики SELinux .SH ОБЗОР .B checkmodule .I "[\-h] [\-b] [\-C] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]" .SH "ОПИСАНИЕ" Эта страница руководства содержит описание команды .BR checkmodule. .PP .B checkmodule - это программа, которая проверяет и компилирует модуль политики безопасности SELinux в двоичное представление. Она может создавать либо базовый модуль политики (по умолчанию), либо небазовый модуль политики (параметр \-m); обычно требуется создать небазовый модуль политики для последующего добавления в существующее хранилище модулей, в котором уже есть базовый модуль, предоставленный базовой политикой. Используйте semodule_package, чтобы объединить этот модуль с соответствующим необязательным файлом контекстов файлов и таким образом создать пакет политики, а затем используйте semodule для установки пакета модуля в хранилище модулей и загрузите получившуюся политику. .SH ПАРАМЕТРЫ .TP .B \-b,\-\-binary Прочитать существующий файл двоичного модуля политики вместо исходного файла модуля политики. Этот параметр полезен при разработке/отладке. .TP .B \-C,\-\-cil Записать файл политики CIL, а не двоичный файл политики. .TP .B \-h,\-\-help Вывести справку. .TP .B \-m Создать небазовый модуль политики. .TP .B \-M,\-\-mls Включить поддержку MLS/MCS при проверке и компиляции модуля политики. .TP .B \-V,\-\-version Показать версии политики, созданные этой программой. Обратите внимание, что в настоящее время не поддерживается сборка более ранних версий. .TP .B \-o,\-\-output filename Записать файл двоичного модуля политики с указанным именем файла. Без указания имени файла checkmodule только проверит синтаксис исходного файла модуля и не будет создавать двоичный модуль. .TP .B \-U,\-\-handle-unknown Указать, как ядро должно обрабатывать неизвестные классы или разрешения (запрещать, разрешать или отклонять). .SH ПРИМЕР .nf # Собрать небазовый модуль политики с включённой системой безопасности MLS/MCS. $ checkmodule \-M \-m httpd.te \-o httpd.mod .fi .SH "СМОТРИТЕ ТАКЖЕ" .B semodule(8), semodule_package(8) Документация SELinux по адресу http://www.nsa.gov/research/selinux, в частности - "Настройка политики SELinux". .SH АВТОРЫ Эта страница руководства была скопирована со страницы руководства checkpolicy, написанной Arpad Magosanyi , и отредактирована Dan Walsh . Программа была написана Stephen Smalley . Перевод на русский язык выполнила Герасименко Олеся . checkpolicy/ru/checkpolicy.80100644 0000000 0000000 00000005655 13756670063 015146 0ustar000000000 0000000 .TH CHECKPOLICY 8 .SH ИМЯ checkpolicy \- компилятор политики SELinux .SH ОБЗОР .B checkpolicy .I "[\-b[F]] [\-C] [\-d] [\-M] [\-c policyvers] [\-o output_file] [input_file]" .br .SH "ОПИСАНИЕ" Эта страница руководства содержит описание команды .BR checkpolicy. .PP .B checkpolicy - это программа, которая проверяет и компилирует конфигурацию политики безопасности SELinux в двоичное представление, которое можно загрузить в ядро. Если имя входного файла не указано, checkpolicy попытается выполнить чтение из policy.conf или policy (если указан флаг \-b). .SH ПАРАМЕТРЫ .TP .B \-b,\-\-binary Прочитать существующий двоичный файл политики, а не исходный файл policy.conf. .TP .B \-C,\-\-cil Записать файл политики CIL, а не двоичный файл политики. .TP .B \-d,\-\-debug Войти в режим отладки после загрузки политики. .TP .B \-F,\-\-conf Записать файл policy.conf, а не двоичный файл политики. Этот параметр можно использовать только при работе с двоичным файлом политики. .TP .B \-M,\-\-mls Включить политику MLS при проверке и компиляции политики. .TP .B \-o,\-\-output filename Записать двоичный файл политики с указанным именем файла. .TP .B \-c policyvers Указать версию политики (по умолчанию используется последняя). .TP .B \-t,\-\-target Указать целевую платформу (selinux или xen). .TP .B \-U,\-\-handle-unknown Указать, как ядро должно обрабатывать неизвестные классы или разрешения (запрещать, разрешать или отклонять). .TP .B \-V,\-\-version Показать сведения о версии. .TP .B \-h,\-\-help Показать сведения об использовании. .SH "СМОТРИТЕ ТАКЖЕ" Документация SELinux по адресу http://www.nsa.gov/research/selinux, в частности - "Настройка политики SELinux". .SH АВТОРЫ Эта страница руководства была написана Arpad Magosanyi , и отредактирована Stephen Smalley . Программа была написана Stephen Smalley . Перевод на русский язык выполнила Герасименко Олеся . checkpolicy/test/0040755 0000000 0000000 00000000000 13756670063 013101 5ustar000000000 0000000 checkpolicy/test/.gitignore0100644 0000000 0000000 00000000016 13756670063 015063 0ustar000000000 0000000 dismod dispol checkpolicy/test/Makefile0100644 0000000 0000000 00000001067 13756670063 014542 0ustar000000000 0000000 # # Makefile for building the dispol program # CFLAGS ?= -g -Wall -W -Werror -O2 -pipe # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there # is no need to define a value for LDLIBS_LIBSEPOLA ifeq ($(LIBSEPOLA),) LDLIBS_LIBSEPOLA := -l:libsepol.a endif all: dispol dismod dispol: dispol.o $(LIBSEPOLA) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) dismod: dismod.o $(LIBSEPOLA) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) clean: -rm -f dispol dismod *.o checkpolicy/test/dismod.c0100644 0000000 0000000 00000061150 13756670063 014524 0ustar000000000 0000000 /* Authors: Frank Mayer and Karl MacMillan * * Copyright (C) 2003,2004,2005 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* * dismod.c * * Test program to the contents of a binary policy in text * form. * * dismod binary_mod_file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if __BYTE_ORDER == __LITTLE_ENDIAN #define le32_to_cpu(x) (x) #else #define le32_to_cpu(x) bswap_32(x) #endif #define DISPLAY_AVBLOCK_COND_AVTAB 0 #define DISPLAY_AVBLOCK_UNCOND_AVTAB 1 #define DISPLAY_AVBLOCK_ROLE_TYPE_NODE 2 /* unused? */ #define DISPLAY_AVBLOCK_ROLE_TRANS 3 #define DISPLAY_AVBLOCK_ROLE_ALLOW 4 #define DISPLAY_AVBLOCK_REQUIRES 5 #define DISPLAY_AVBLOCK_DECLARES 6 #define DISPLAY_AVBLOCK_FILENAME_TRANS 7 static policydb_t policydb; extern unsigned int ss_initialized; int policyvers = MOD_POLICYDB_VERSION_BASE; static const char *symbol_labels[9] = { "commons", "classes", "roles ", "types ", "users ", "bools ", "levels ", "cats ", "attribs" }; static __attribute__((__noreturn__)) void usage(const char *progname) { printf("usage: %s binary_pol_file\n\n", progname); exit(1); } static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p, FILE * fp) { char *perm; fprintf(fp, "{"); perm = sepol_av_to_string(p, class, mask); if (perm) fprintf(fp, "%s ", perm); fprintf(fp, "}"); } static void render_access_bitmap(ebitmap_t * map, uint32_t class, policydb_t * p, FILE * fp) { unsigned int i; char *perm; fprintf(fp, "{"); for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) { if (ebitmap_get_bit(map, i)) { perm = sepol_av_to_string(p, class, 1 << i); if (perm) fprintf(fp, " %s", perm); } } fprintf(fp, " }"); } static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type, uint32_t symbol_value, const char *prefix) { char *id = p->sym_val_to_name[symbol_type][symbol_value]; scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id); assert(scope != NULL); if (scope->scope == SCOPE_REQ) { fprintf(fp, " [%s%s]", prefix, id); } else { fprintf(fp, " %s%s", prefix, id); } } int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy, FILE * fp) { unsigned int i, num_types; if (set->flags & TYPE_STAR) { fprintf(fp, " * "); return 0; } else if (set->flags & TYPE_COMP) { fprintf(fp, " ~"); } num_types = 0; if (flags & RULE_SELF) { num_types++; } for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); i++) { if (!ebitmap_get_bit(&set->types, i)) continue; num_types++; if (num_types > 1) break; } if (num_types <= 1) { for (i = ebitmap_startbit(&set->negset); i < ebitmap_length(&set->negset); i++) { if (!ebitmap_get_bit(&set->negset, i)) continue; num_types++; if (num_types > 1) break; } } if (num_types > 1) fprintf(fp, "{"); for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types); i++) { if (!ebitmap_get_bit(&set->types, i)) continue; display_id(policy, fp, SYM_TYPES, i, ""); } for (i = ebitmap_startbit(&set->negset); i < ebitmap_length(&set->negset); i++) { if (!ebitmap_get_bit(&set->negset, i)) continue; display_id(policy, fp, SYM_TYPES, i, "-"); } if (flags & RULE_SELF) { fprintf(fp, " self"); } if (num_types > 1) fprintf(fp, " }"); return 0; } int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp) { unsigned int i, num = 0; if (roles->flags & ROLE_STAR) { fprintf(fp, " * "); return 0; } else if (roles->flags & ROLE_COMP) { fprintf(fp, " ~"); } for (i = ebitmap_startbit(&roles->roles); i < ebitmap_length(&roles->roles); i++) { if (!ebitmap_get_bit(&roles->roles, i)) continue; num++; if (num > 1) { fprintf(fp, "{"); break; } } for (i = ebitmap_startbit(&roles->roles); i < ebitmap_length(&roles->roles); i++) { if (ebitmap_get_bit(&roles->roles, i)) display_id(p, fp, SYM_ROLES, i, ""); } if (num > 1) fprintf(fp, " }"); return 0; } int display_avrule(avrule_t * avrule, policydb_t * policy, FILE * fp) { class_perm_node_t *cur; int num_classes; if (avrule == NULL) { fprintf(fp, " \n"); return 0; } if (avrule->specified & AVRULE_AV) { if (avrule->specified & AVRULE_ALLOWED) { fprintf(fp, " allow"); } if (avrule->specified & AVRULE_AUDITALLOW) { fprintf(fp, " auditallow "); } if (avrule->specified & AVRULE_DONTAUDIT) { fprintf(fp, " dontaudit"); } } else if (avrule->specified & AVRULE_TYPE) { if (avrule->specified & AVRULE_TRANSITION) { fprintf(fp, " type_transition"); } if (avrule->specified & AVRULE_MEMBER) { fprintf(fp, " type_member"); } if (avrule->specified & AVRULE_CHANGE) { fprintf(fp, " type_change"); } } else if (avrule->specified & AVRULE_NEVERALLOW) { fprintf(fp, " neverallow"); } else if (avrule->specified & AVRULE_XPERMS) { if (avrule->specified & AVRULE_XPERMS_ALLOWED) fprintf(fp, "allowxperm "); else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW) fprintf(fp, "auditallowxperm "); else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT) fprintf(fp, "dontauditxperm "); } else { fprintf(fp, " ERROR: no valid rule type specified\n"); return -1; } if (display_type_set(&avrule->stypes, 0, policy, fp)) return -1; if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp)) return -1; fprintf(fp, " :"); cur = avrule->perms; num_classes = 0; while (cur) { num_classes++; if (num_classes > 1) break; cur = cur->next; } if (num_classes > 1) fprintf(fp, " {"); cur = avrule->perms; while (cur) { display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, ""); cur = cur->next; } if (num_classes > 1) fprintf(fp, " }"); fprintf(fp, " "); if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) { render_access_mask(avrule->perms->data, avrule->perms->tclass, policy, fp); } else if (avrule->specified & AVRULE_TYPE) { display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); } else if (avrule->specified & AVRULE_XPERMS) { avtab_extended_perms_t xperms; int i; if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION) xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER) xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; else { fprintf(fp, " ERROR: no valid xperms specified\n"); return -1; } xperms.driver = avrule->xperms->driver; for (i = 0; i < EXTENDED_PERMS_LEN; i++) xperms.perms[i] = avrule->xperms->perms[i]; fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms)); } fprintf(fp, ";\n"); return 0; } int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { type_datum_t *type; FILE *fp; unsigned int i, first_attrib = 1; type = (type_datum_t *) datum; fp = (FILE *) data; if (type->primary) { display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, ""); fprintf(fp, " [%d]: ", type->s.value); } else { /* as that aliases have no value of their own and that * they can never be required by a module, use this * alternative way of displaying a name */ fprintf(fp, " %s [%d]: ", (char *)key, type->s.value); } if (type->flavor == TYPE_ATTRIB) { fprintf(fp, "attribute for types"); for (i = ebitmap_startbit(&type->types); i < ebitmap_length(&type->types); i++) { if (!ebitmap_get_bit(&type->types, i)) continue; if (first_attrib) { first_attrib = 0; } else { fprintf(fp, ","); } display_id(&policydb, fp, SYM_TYPES, i, ""); } } else if (type->primary) { fprintf(fp, "type"); } else { fprintf(fp, "alias for type"); display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, ""); } fprintf(fp, " flags:%x\n", type->flags); return 0; } int display_types(policydb_t * p, FILE * fp) { if (hashtab_map(p->p_types.table, display_type_callback, fp)) return -1; return 0; } int display_users(policydb_t * p, FILE * fp) { unsigned int i, j; ebitmap_t *bitmap; for (i = 0; i < p->p_users.nprim; i++) { display_id(p, fp, SYM_USERS, i, ""); fprintf(fp, ":"); bitmap = &(p->user_val_to_struct[i]->roles.roles); for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap); j++) { if (ebitmap_get_bit(bitmap, j)) { display_id(p, fp, SYM_ROLES, j, ""); } } fprintf(fp, "\n"); } return 0; } int display_bools(policydb_t * p, FILE * fp) { unsigned int i; for (i = 0; i < p->p_bools.nprim; i++) { display_id(p, fp, SYM_BOOLS, i, ""); fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state); } return 0; } void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", p->p_bool_val_to_name[cur->bool - 1]); break; case COND_NOT: fprintf(fp, "! "); break; case COND_OR: fprintf(fp, "|| "); break; case COND_AND: fprintf(fp, "&& "); break; case COND_XOR: fprintf(fp, "^ "); break; case COND_EQ: fprintf(fp, "== "); break; case COND_NEQ: fprintf(fp, "!= "); break; default: fprintf(fp, "error!"); break; } } } void display_policycon(FILE * fp) { /* There was an attempt to implement this at one time. Look through * git history to find it. */ fprintf(fp, "Sorry, not implemented\n"); } void display_initial_sids(policydb_t * p, FILE * fp) { ocontext_t *cur; char *user, *role, *type; fprintf(fp, "Initial SIDs:\n"); for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) { user = p->p_user_val_to_name[cur->context[0].user - 1]; role = p->p_role_val_to_name[cur->context[0].role - 1]; type = p->p_type_val_to_name[cur->context[0].type - 1]; fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n", cur->u.name, cur->sid[0], user, role, type); } #if 0 fprintf(fp, "Policy Initial SIDs:\n"); for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) { user = p->p_user_val_to_name[cur->context[0].user - 1]; role = p->p_role_val_to_name[cur->context[0].role - 1]; type = p->p_type_val_to_name[cur->context[0].type - 1]; fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n", cur->u.name, cur->sid[0], user, role, type); } #endif } void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp) { unsigned int i, num = 0; for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) { if (!ebitmap_get_bit(classes, i)) continue; num++; if (num > 1) { fprintf(fp, "{"); break; } } for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) { if (ebitmap_get_bit(classes, i)) display_id(p, fp, SYM_CLASSES, i, ""); } if (num > 1) fprintf(fp, " }"); } void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp) { for (; tr; tr = tr->next) { fprintf(fp, "role transition "); display_mod_role_set(&tr->roles, p, fp); display_type_set(&tr->types, 0, p, fp); fprintf(fp, " :"); display_class_set(&tr->classes, p, fp); display_id(p, fp, SYM_ROLES, tr->new_role - 1, ""); fprintf(fp, "\n"); } } void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp) { for (; ra; ra = ra->next) { fprintf(fp, "role allow "); display_mod_role_set(&ra->roles, p, fp); display_mod_role_set(&ra->new_roles, p, fp); fprintf(fp, "\n"); } } static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp) { fprintf(fp, "filename transition"); for (; tr; tr = tr->next) { display_type_set(&tr->stypes, 0, p, fp); display_type_set(&tr->ttypes, 0, p, fp); display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":"); display_id(p, fp, SYM_TYPES, tr->otype - 1, ""); fprintf(fp, " %s\n", tr->name); } } int role_display_callback(hashtab_key_t key __attribute__((unused)), hashtab_datum_t datum, void *data) { role_datum_t *role; FILE *fp; role = (role_datum_t *) datum; fp = (FILE *) data; fprintf(fp, "role:"); display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, ""); fprintf(fp, " types: "); display_type_set(&role->types, 0, &policydb, fp); fprintf(fp, "\n"); return 0; } static int display_scope_index(scope_index_t * indices, policydb_t * p, FILE * out_fp) { unsigned int i; for (i = 0; i < SYM_NUM; i++) { unsigned int any_found = 0, j; fprintf(out_fp, "%s:", symbol_labels[i]); for (j = ebitmap_startbit(&indices->scope[i]); j < ebitmap_length(&indices->scope[i]); j++) { if (ebitmap_get_bit(&indices->scope[i], j)) { any_found = 1; fprintf(out_fp, " %s", p->sym_val_to_name[i][j]); if (i == SYM_CLASSES) { if (j < indices->class_perms_len) { render_access_bitmap(indices-> class_perms_map + j, j + 1, p, out_fp); } else { fprintf(out_fp, ""); } } } } if (!any_found) { fprintf(out_fp, " "); } fprintf(out_fp, "\n"); } return 0; } #if 0 int display_cond_expressions(policydb_t * p, FILE * fp) { cond_node_t *cur; cond_av_list_t *av_cur; for (cur = p->cond_list; cur != NULL; cur = cur->next) { fprintf(fp, "expression: "); display_expr(p, cur->expr, fp); fprintf(fp, "current state: %d\n", cur->cur_state); fprintf(fp, "True list:\n"); for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) { fprintf(fp, "\t"); render_av_rule(&av_cur->node->key, &av_cur->node->datum, RENDER_CONDITIONAL, p, fp); } fprintf(fp, "False list:\n"); for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) { fprintf(fp, "\t"); render_av_rule(&av_cur->node->key, &av_cur->node->datum, RENDER_CONDITIONAL, p, fp); } } return 0; } int change_bool(char *name, int state, policydb_t * p, FILE * fp) { cond_bool_datum_t *bool; bool = hashtab_search(p->p_bools.table, name); if (bool == NULL) { fprintf(fp, "Could not find bool %s\n", name); return -1; } bool->state = state; evaluate_conds(p); return 0; } #endif int display_avdecl(avrule_decl_t * decl, int field, policydb_t * policy, FILE * out_fp) { fprintf(out_fp, "decl %u:%s\n", decl->decl_id, (decl->enabled ? " [enabled]" : "")); switch (field) { case DISPLAY_AVBLOCK_COND_AVTAB:{ cond_list_t *cond = decl->cond_list; avrule_t *avrule; while (cond) { fprintf(out_fp, "expression: "); display_expr(&policydb, cond->expr, out_fp); fprintf(out_fp, "current state: %d\n", cond->cur_state); fprintf(out_fp, "True list:\n"); avrule = cond->avtrue_list; while (avrule) { display_avrule(avrule, &policydb, out_fp); avrule = avrule->next; } fprintf(out_fp, "False list:\n"); avrule = cond->avfalse_list; while (avrule) { display_avrule(avrule, &policydb, out_fp); avrule = avrule->next; } cond = cond->next; } break; } case DISPLAY_AVBLOCK_UNCOND_AVTAB:{ avrule_t *avrule = decl->avrules; if (avrule == NULL) { fprintf(out_fp, " \n"); } while (avrule != NULL) { if (display_avrule(avrule, policy, out_fp)) return -1; avrule = avrule->next; } break; } case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{ /* role_type_node */ break; } case DISPLAY_AVBLOCK_ROLE_TRANS:{ display_role_trans(decl->role_tr_rules, policy, out_fp); break; } case DISPLAY_AVBLOCK_ROLE_ALLOW:{ display_role_allow(decl->role_allow_rules, policy, out_fp); break; } case DISPLAY_AVBLOCK_REQUIRES:{ if (display_scope_index (&decl->required, policy, out_fp)) { return -1; } break; } case DISPLAY_AVBLOCK_DECLARES:{ if (display_scope_index (&decl->declared, policy, out_fp)) { return -1; } break; } case DISPLAY_AVBLOCK_FILENAME_TRANS: display_filename_trans(decl->filename_trans_rules, policy, out_fp); break; default:{ assert(0); } } return 0; /* should never get here */ } int display_avblock(int field, policydb_t * policy, FILE * out_fp) { avrule_block_t *block = policydb.global; while (block != NULL) { fprintf(out_fp, "--- begin avrule block ---\n"); avrule_decl_t *decl = block->branch_list; while (decl != NULL) { if (display_avdecl(decl, field, policy, out_fp)) { return -1; } decl = decl->next; } block = block->next; } return 0; } int display_handle_unknown(policydb_t * p, FILE * out_fp) { if (p->handle_unknown == ALLOW_UNKNOWN) fprintf(out_fp, "Allow unknown classes and perms\n"); else if (p->handle_unknown == DENY_UNKNOWN) fprintf(out_fp, "Deny unknown classes and perms\n"); else if (p->handle_unknown == REJECT_UNKNOWN) fprintf(out_fp, "Reject unknown classes and perms\n"); return 0; } static int read_policy(char *filename, policydb_t * policy) { FILE *in_fp; struct policy_file f; int retval; uint32_t buf[1]; if ((in_fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); exit(1); } policy_file_init(&f); f.type = PF_USE_STDIO; f.fp = in_fp; /* peek at the first byte. if they are indicative of a package use the package reader, otherwise use the normal policy reader */ if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) { fprintf(stderr, "Could not read from policy.\n"); exit(1); } rewind(in_fp); if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) { sepol_module_package_t *package; if (sepol_module_package_create(&package)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); exit(1); } package->policy = (sepol_policydb_t *) policy; package->file_contexts = NULL; retval = sepol_module_package_read(package, (sepol_policy_file_t *) & f, 1); free(package->file_contexts); } else { if (policydb_init(policy)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); exit(1); } retval = policydb_read(policy, &f, 1); } fclose(in_fp); return retval; } static void link_module(policydb_t * base, FILE * out_fp) { char module_name[80] = { 0 }; int ret; policydb_t module, *mods = &module; if (base->policy_type != POLICY_BASE) { printf("Can only link if initial file was a base policy.\n"); return; } printf("\nModule filename: "); if (fgets(module_name, sizeof(module_name), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); exit(1); } module_name[strlen(module_name) - 1] = '\0'; /* remove LF */ if (module_name[0] == '\0') { return; } /* read the binary policy */ fprintf(out_fp, "Reading module...\n"); if (read_policy(module_name, mods)) { fprintf(stderr, "%s: error(s) encountered while loading policy\n", module_name); exit(1); } if (module.policy_type != POLICY_MOD) { fprintf(stderr, "This file is not a loadable policy module.\n"); exit(1); } if (policydb_index_classes(&module) || policydb_index_others(NULL, &module, 0)) { fprintf(stderr, "Could not index module.\n"); exit(1); } ret = link_modules(NULL, base, &mods, 1, 0); if (ret != 0) { printf("Link failed (error %d)\n", ret); printf("(You will probably need to restart dismod.)\n"); } policydb_destroy(&module); return; } static void display_policycaps(policydb_t * p, FILE * fp) { ebitmap_node_t *node; const char *capname; char buf[64]; unsigned int i; fprintf(fp, "policy capabilities:\n"); ebitmap_for_each_bit(&p->policycaps, node, i) { if (ebitmap_node_get_bit(node, i)) { capname = sepol_polcap_getname(i); if (capname == NULL) { snprintf(buf, sizeof(buf), "unknown (%d)", i); capname = buf; } fprintf(fp, "\t%s\n", capname); } } } int menu(void) { printf("\nSelect a command:\n"); printf("1) display unconditional AVTAB\n"); printf("2) display conditional AVTAB\n"); printf("3) display users\n"); printf("4) display bools\n"); printf("5) display roles\n"); printf("6) display types, attributes, and aliases\n"); printf("7) display role transitions\n"); printf("8) display role allows\n"); printf("9) Display policycon\n"); printf("0) Display initial SIDs\n"); printf("\n"); printf("a) Display avrule requirements\n"); printf("b) Display avrule declarations\n"); printf("c) Display policy capabilities\n"); printf("l) Link in a module\n"); printf("u) Display the unknown handling setting\n"); printf("F) Display filename_trans rules\n"); printf("\n"); printf("f) set output file\n"); printf("m) display menu\n"); printf("q) quit\n"); return 0; } int main(int argc, char **argv) { FILE *out_fp = stdout; char ans[81], OutfileName[121]; if (argc != 2) usage(argv[0]); /* read the binary policy */ fprintf(out_fp, "Reading policy...\n"); if (policydb_init(&policydb)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); exit(1); } if (read_policy(argv[1], &policydb)) { fprintf(stderr, "%s: error(s) encountered while loading policy\n", argv[0]); exit(1); } if (policydb.policy_type != POLICY_BASE && policydb.policy_type != POLICY_MOD) { fprintf(stderr, "This file is neither a base nor loadable policy module.\n"); exit(1); } if (policydb_index_classes(&policydb)) { fprintf(stderr, "Error indexing classes\n"); exit(1); } if (policydb_index_others(NULL, &policydb, 1)) { fprintf(stderr, "Error indexing others\n"); exit(1); } if (policydb.policy_type == POLICY_BASE) { printf("Binary base policy file loaded.\n\n"); } else { printf("Binary policy module file loaded.\n"); printf("Module name: %s\n", policydb.name); printf("Module version: %s\n", policydb.version); printf("\n"); } menu(); for (;;) { printf("\nCommand (\'m\' for menu): "); if (fgets(ans, sizeof(ans), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); continue; } switch (ans[0]) { case '1': fprintf(out_fp, "unconditional avtab:\n"); display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB, &policydb, out_fp); break; case '2': fprintf(out_fp, "conditional avtab:\n"); display_avblock(DISPLAY_AVBLOCK_COND_AVTAB, &policydb, out_fp); break; case '3': display_users(&policydb, out_fp); break; case '4': display_bools(&policydb, out_fp); break; case '5': if (hashtab_map (policydb.p_roles.table, role_display_callback, out_fp)) exit(1); break; case '6': if (display_types(&policydb, out_fp)) { fprintf(stderr, "Error displaying types\n"); exit(1); } break; case '7': fprintf(out_fp, "role transitions:\n"); display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, &policydb, out_fp); break; case '8': fprintf(out_fp, "role allows:\n"); display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, &policydb, out_fp); break; case '9': display_policycon(out_fp); break; case '0': display_initial_sids(&policydb, out_fp); break; case 'a': fprintf(out_fp, "avrule block requirements:\n"); display_avblock(DISPLAY_AVBLOCK_REQUIRES, &policydb, out_fp); break; case 'b': fprintf(out_fp, "avrule block declarations:\n"); display_avblock(DISPLAY_AVBLOCK_DECLARES, &policydb, out_fp); break; case 'c': display_policycaps(&policydb, out_fp); break; case 'u': case 'U': display_handle_unknown(&policydb, out_fp); break; case 'f': printf ("\nFilename for output ( for screen output): "); if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); break; } OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ if (strlen(OutfileName) == 0) out_fp = stdout; else if ((out_fp = fopen(OutfileName, "w")) == NULL) { fprintf(stderr, "Cannot open output file %s\n", OutfileName); out_fp = stdout; } if (out_fp != stdout) printf("\nOutput to file: %s\n", OutfileName); break; case 'F': fprintf(out_fp, "filename_trans rules:\n"); display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS, &policydb, out_fp); break; case 'l': link_module(&policydb, out_fp); break; case 'q': policydb_destroy(&policydb); exit(0); break; case 'm': menu(); break; default: printf("\nInvalid choice\n"); menu(); break; } } exit(EXIT_SUCCESS); } checkpolicy/test/dispol.c0100644 0000000 0000000 00000033465 13756670063 014547 0ustar000000000 0000000 /* Authors: Frank Mayer and Karl MacMillan * * Copyright (C) 2003 Tresys Technology, LLC * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. */ /* * displaypol.c * * Test program to the contents of a binary policy in text * form. This program currently only displays the * avtab (including conditional avtab) rules. * * displaypol binary_pol_file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static policydb_t policydb; static __attribute__((__noreturn__)) void usage(const char *progname) { printf("usage: %s binary_pol_file\n\n", progname); exit(1); } int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, FILE * fp) { char *perm; fprintf(fp, "{"); perm = sepol_av_to_string(p, key->target_class, mask); if (perm) fprintf(fp, "%s ", perm); fprintf(fp, "}"); return 0; } int render_type(uint32_t type, policydb_t * p, FILE * fp) { fprintf(fp, "%s", p->p_type_val_to_name[type - 1]); return 0; } int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) { char *stype, *ttype, *tclass; stype = p->p_type_val_to_name[key->source_type - 1]; ttype = p->p_type_val_to_name[key->target_type - 1]; tclass = p->p_class_val_to_name[key->target_class - 1]; if (stype && ttype) fprintf(fp, "%s %s : %s ", stype, ttype, tclass); else if (stype) fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass); else if (ttype) fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass); else fprintf(fp, "%u %u : %s ", key->source_type, key->target_type, tclass); return 0; } /* 'what' values for this function */ #define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */ #define RENDER_ENABLED 0x0002 #define RENDER_DISABLED 0x0004 #define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED) int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, policydb_t * p, FILE * fp) { if (!(what & RENDER_UNCONDITIONAL)) { if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED) && !(key-> specified & AVTAB_ENABLED)) || ((what & RENDER_DISABLED) && (key-> specified & AVTAB_ENABLED)))) { return 0; /* doesn't match selection criteria */ } } if (!(what & RENDER_UNCONDITIONAL)) { if (key->specified & AVTAB_ENABLED) fprintf(fp, "[enabled] "); else if (!(key->specified & AVTAB_ENABLED)) fprintf(fp, "[disabled] "); } if (key->specified & AVTAB_AV) { if (key->specified & AVTAB_ALLOWED) { fprintf(fp, "allow "); render_key(key, p, fp); render_access_mask(datum->data, key, p, fp); fprintf(fp, ";\n"); } if (key->specified & AVTAB_AUDITALLOW) { fprintf(fp, "auditallow "); render_key(key, p, fp); render_access_mask(datum->data, key, p, fp); fprintf(fp, ";\n"); } if (key->specified & AVTAB_AUDITDENY) { fprintf(fp, "dontaudit "); render_key(key, p, fp); /* We inverse the mask for dontaudit since the mask is internally stored * as a auditdeny mask */ render_access_mask(~datum->data, key, p, fp); fprintf(fp, ";\n"); } } else if (key->specified & AVTAB_TYPE) { if (key->specified & AVTAB_TRANSITION) { fprintf(fp, "type_transition "); render_key(key, p, fp); render_type(datum->data, p, fp); fprintf(fp, ";\n"); } if (key->specified & AVTAB_MEMBER) { fprintf(fp, "type_member "); render_key(key, p, fp); render_type(datum->data, p, fp); fprintf(fp, ";\n"); } if (key->specified & AVTAB_CHANGE) { fprintf(fp, "type_change "); render_key(key, p, fp); render_type(datum->data, p, fp); fprintf(fp, ";\n"); } } else if (key->specified & AVTAB_XPERMS) { if (key->specified & AVTAB_XPERMS_ALLOWED) fprintf(fp, "allowxperm "); else if (key->specified & AVTAB_XPERMS_AUDITALLOW) fprintf(fp, "auditallowxperm "); else if (key->specified & AVTAB_XPERMS_DONTAUDIT) fprintf(fp, "dontauditxperm "); render_key(key, p, fp); fprintf(fp, "%s;\n", sepol_extended_perms_to_string(datum->xperms)); } else { fprintf(fp, " ERROR: no valid rule type specified\n"); return -1; } return 0; } int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) { unsigned int i; avtab_ptr_t cur; /* hmm...should have used avtab_map. */ for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { render_av_rule(&cur->key, &cur->datum, what, p, fp); } } fprintf(fp, "\n"); return 0; } int display_bools(policydb_t * p, FILE * fp) { unsigned int i; for (i = 0; i < p->p_bools.nprim; i++) { fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i], p->bool_val_to_struct[i]->state); } return 0; } void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", p->p_bool_val_to_name[cur->bool - 1]); break; case COND_NOT: fprintf(fp, "! "); break; case COND_OR: fprintf(fp, "|| "); break; case COND_AND: fprintf(fp, "&& "); break; case COND_XOR: fprintf(fp, "^ "); break; case COND_EQ: fprintf(fp, "== "); break; case COND_NEQ: fprintf(fp, "!= "); break; default: fprintf(fp, "error!"); break; } } } int display_cond_expressions(policydb_t * p, FILE * fp) { cond_node_t *cur; cond_av_list_t *av_cur; for (cur = p->cond_list; cur != NULL; cur = cur->next) { fprintf(fp, "expression: "); display_expr(p, cur->expr, fp); fprintf(fp, "current state: %d\n", cur->cur_state); fprintf(fp, "True list:\n"); for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) { fprintf(fp, "\t"); render_av_rule(&av_cur->node->key, &av_cur->node->datum, RENDER_CONDITIONAL, p, fp); } fprintf(fp, "False list:\n"); for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) { fprintf(fp, "\t"); render_av_rule(&av_cur->node->key, &av_cur->node->datum, RENDER_CONDITIONAL, p, fp); } } return 0; } int display_handle_unknown(policydb_t * p, FILE * out_fp) { if (p->handle_unknown == ALLOW_UNKNOWN) fprintf(out_fp, "Allow unknown classes and permissions\n"); else if (p->handle_unknown == DENY_UNKNOWN) fprintf(out_fp, "Deny unknown classes and permissions\n"); else if (p->handle_unknown == REJECT_UNKNOWN) fprintf(out_fp, "Reject unknown classes and permissions\n"); return 0; } int change_bool(char *name, int state, policydb_t * p, FILE * fp) { cond_bool_datum_t *bool; bool = hashtab_search(p->p_bools.table, name); if (bool == NULL) { fprintf(fp, "Could not find bool %s\n", name); return -1; } bool->state = state; evaluate_conds(p); return 0; } static void display_policycaps(policydb_t * p, FILE * fp) { ebitmap_node_t *node; const char *capname; char buf[64]; unsigned int i; fprintf(fp, "policy capabilities:\n"); ebitmap_for_each_bit(&p->policycaps, node, i) { if (ebitmap_node_get_bit(node, i)) { capname = sepol_polcap_getname(i); if (capname == NULL) { snprintf(buf, sizeof(buf), "unknown (%d)", i); capname = buf; } fprintf(fp, "\t%s\n", capname); } } } static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type, uint32_t symbol_value, const char *prefix) { const char *id = p->sym_val_to_name[symbol_type][symbol_value]; fprintf(fp, " %s%s", prefix, id); } static void display_permissive(policydb_t *p, FILE *fp) { ebitmap_node_t *node; unsigned int i; fprintf(fp, "permissive sids:\n"); ebitmap_for_each_bit(&p->permissive_map, node, i) { if (ebitmap_node_get_bit(node, i)) { fprintf(fp, "\t"); display_id(p, fp, SYM_TYPES, i - 1, ""); fprintf(fp, "\n"); } } } static void display_role_trans(policydb_t *p, FILE *fp) { role_trans_t *rt; fprintf(fp, "role_trans rules:\n"); for (rt = p->role_tr; rt; rt = rt->next) { display_id(p, fp, SYM_ROLES, rt->role - 1, ""); display_id(p, fp, SYM_TYPES, rt->type - 1, ""); display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":"); display_id(p, fp, SYM_ROLES, rt->new_role - 1, ""); fprintf(fp, "\n"); } } struct filenametr_display_args { policydb_t *p; FILE *fp; }; static int filenametr_display(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { struct filename_trans *ft = (struct filename_trans *)key; struct filename_trans_datum *ftdatum = datum; struct filenametr_display_args *args = ptr; policydb_t *p = args->p; FILE *fp = args->fp; display_id(p, fp, SYM_TYPES, ft->stype - 1, ""); display_id(p, fp, SYM_TYPES, ft->ttype - 1, ""); display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":"); display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, ""); fprintf(fp, " %s\n", ft->name); return 0; } static void display_filename_trans(policydb_t *p, FILE *fp) { struct filenametr_display_args args; fprintf(fp, "filename_trans rules:\n"); args.p = p; args.fp = fp; hashtab_map(p->filename_trans, filenametr_display, &args); } int menu(void) { printf("\nSelect a command:\n"); printf("1) display unconditional AVTAB\n"); printf("2) display conditional AVTAB (entirely)\n"); printf("3) display conditional AVTAB (only ENABLED rules)\n"); printf("4) display conditional AVTAB (only DISABLED rules)\n"); printf("5) display conditional bools\n"); printf("6) display conditional expressions\n"); printf("7) change a boolean value\n"); printf("8) display role transitions\n"); printf("\n"); printf("c) display policy capabilities\n"); printf("p) display the list of permissive types\n"); printf("u) display unknown handling setting\n"); printf("F) display filename_trans rules\n"); printf("\n"); printf("f) set output file\n"); printf("m) display menu\n"); printf("q) quit\n"); return 0; } int main(int argc, char **argv) { FILE *out_fp = stdout; char ans[81], OutfileName[121]; int fd, ret; struct stat sb; void *map; char *name; int state; struct policy_file pf; if (argc != 2) usage(argv[0]); fd = open(argv[1], O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", argv[1], strerror(errno)); exit(1); } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", argv[1], strerror(errno)); exit(1); } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", argv[1], strerror(errno)); exit(1); } /* read the binary policy */ fprintf(out_fp, "Reading policy...\n"); policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = map; pf.len = sb.st_size; if (policydb_init(&policydb)) { fprintf(stderr, "%s: Out of memory!\n", argv[0]); exit(1); } ret = policydb_read(&policydb, &pf, 1); if (ret) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", argv[0]); exit(1); } fprintf(stdout, "binary policy file loaded\n\n"); close(fd); menu(); for (;;) { printf("\nCommand (\'m\' for menu): "); if (fgets(ans, sizeof(ans), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); continue; } switch (ans[0]) { case '1': display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL, &policydb, out_fp); break; case '2': display_avtab(&policydb.te_cond_avtab, RENDER_CONDITIONAL, &policydb, out_fp); break; case '3': display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED, &policydb, out_fp); break; case '4': display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED, &policydb, out_fp); break; case '5': display_bools(&policydb, out_fp); break; case '6': display_cond_expressions(&policydb, out_fp); break; case '7': printf("name? "); if (fgets(ans, sizeof(ans), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); break; } ans[strlen(ans) - 1] = 0; name = malloc((strlen(ans) + 1) * sizeof(char)); if (name == NULL) { fprintf(stderr, "couldn't malloc string.\n"); break; } strcpy(name, ans); printf("state? "); if (fgets(ans, sizeof(ans), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); break; } ans[strlen(ans) - 1] = 0; if (atoi(ans)) state = 1; else state = 0; change_bool(name, state, &policydb, out_fp); free(name); break; case '8': display_role_trans(&policydb, out_fp); break; case 'c': display_policycaps(&policydb, out_fp); break; case 'p': display_permissive(&policydb, out_fp); break; case 'u': case 'U': display_handle_unknown(&policydb, out_fp); break; case 'f': printf ("\nFilename for output ( for screen output): "); if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) { fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); break; } OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */ if (strlen(OutfileName) == 0) out_fp = stdout; else if ((out_fp = fopen(OutfileName, "w")) == NULL) { fprintf(stderr, "Cannot open output file %s\n", OutfileName); out_fp = stdout; } if (out_fp != stdout) printf("\nOutput to file: %s\n", OutfileName); break; case 'F': display_filename_trans(&policydb, out_fp); break; case 'q': policydb_destroy(&policydb); exit(0); break; case 'm': menu(); break; default: printf("\nInvalid choice\n"); menu(); break; } } } /* FLASK */ dbus/0040755 0000000 0000000 00000000000 13756670063 010562 5ustar000000000 0000000 dbus/COPYING0100644 0000000 0000000 00000043131 13756670063 011614 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. dbus/Makefile0100644 0000000 0000000 00000001110 13756670063 012210 0ustar000000000 0000000 PREFIX ?= /usr all: clean: install: -mkdir -p $(DESTDIR)/etc/dbus-1/system.d/ install -m 644 org.selinux.conf $(DESTDIR)/etc/dbus-1/system.d/ -mkdir -p $(DESTDIR)$(PREFIX)/share/dbus-1/system-services install -m 644 org.selinux.service $(DESTDIR)$(PREFIX)/share/dbus-1/system-services -mkdir -p $(DESTDIR)$(PREFIX)/share/polkit-1/actions/ install -m 644 org.selinux.policy $(DESTDIR)$(PREFIX)/share/polkit-1/actions/ -mkdir -p $(DESTDIR)$(PREFIX)/share/system-config-selinux install -m 755 selinux_server.py $(DESTDIR)$(PREFIX)/share/system-config-selinux relabel: test: dbus/VERSION0100644 0000000 0000000 00000000004 13756670063 011621 0ustar000000000 0000000 2.9 dbus/org.selinux.conf0100644 0000000 0000000 00000001027 13756670063 013703 0ustar000000000 0000000 dbus/org.selinux.policy0100644 0000000 0000000 00000006344 13756670063 014264 0ustar000000000 0000000 Red Hat Inc. http://www.redhat.com SELinux write access System policy prevents restorecon access to SELinux no no auth_admin_keep SELinux write access System policy prevents setenforce access to SELinux no no auth_admin_keep SELinux write access System policy prevents semanage access to SELinux no no auth_admin_keep SELinux Read access System policy prevents read access to SELinux no no auth_admin_keep SELinux list modules access System policy prevents read access to SELinux modules no no auth_admin_keep SELinux write access System policy prevents relabel_on_boot access to SELinux no no auth_admin_keep SELinux write access System policy prevents change_default_policy access to SELinux no no auth_admin_keep Change SELinux default enforcing mode System policy prevents change_default_policy access to SELinux no no auth_admin_keep dbus/org.selinux.service0100644 0000000 0000000 00000000143 13756670063 014414 0ustar000000000 0000000 [D-BUS Service] Name=org.selinux Exec=/usr/share/system-config-selinux/selinux_server.py User=root dbus/selinux_client.py0100644 0000000 0000000 00000003067 13756670063 014164 0ustar000000000 0000000 import dbus import dbus.service from sepolicy.sedbus import SELinuxDBus def convert_customization(buf): cust_dict = {} cust_dict["fcontext-equiv"] = {} for i in buf.split("\n"): rec = i.split() if len(rec) == 0: continue if rec[1] == "-D": continue if rec[0] not in cust_dict: cust_dict[rec[0]] = {} if rec[0] == "boolean": cust_dict["boolean"][rec[-1]] = {"active": rec[2] == "-1"} if rec[0] == "login": cust_dict["login"][rec[-1]] = {"seuser": rec[3], "range": rec[5]} if rec[0] == "interface": cust_dict["login"][rec[-1]] = {"type": rec[3]} if rec[0] == "user": cust_dict["user"][rec[-1]] = {"level": rec[3], "range": rec[5], "role": rec[7]} if rec[0] == "port": cust_dict["port"][(rec[-1], rec[-2])] = {"type": rec[3]} if rec[0] == "node": cust_dict["node"][rec[-1]] = {"mask": rec[3], "protocol": rec[5], "type": rec[7]} if rec[0] == "fcontext": if rec[2] == "-e": cust_dict["fcontext-equiv"][(rec[-1])] = {"equiv": rec[3]} else: cust_dict["fcontext"][(rec[-1], rec[3])] = {"type": rec[5]} if rec[0] == "module": cust_dict["module"][rec[-1]] = {"enabled": rec[2] != "-d"} return cust_dict if __name__ == "__main__": try: dbus_proxy = SELinuxDBus() resp = dbus_proxy.customized() print(convert_customization(resp)) except dbus.DBusException as e: print(e) dbus/selinux_server.py0100644 0000000 0000000 00000012127 13756670063 014211 0ustar000000000 0000000 #!/usr/bin/python3 import dbus import dbus.service import dbus.mainloop.glib from gi.repository import GObject import slip.dbus.service from slip.dbus import polkit import os import selinux from subprocess import Popen, PIPE, STDOUT class selinux_server(slip.dbus.service.Object): default_polkit_auth_required = "org.selinux.semanage" def __init__(self, *p, **k): super(selinux_server, self).__init__(*p, **k) # # The semanage method runs a transaction on a series of semanage commands, # these commnds can take the output of customized # @slip.dbus.polkit.require_auth("org.selinux.semanage") @dbus.service.method("org.selinux", in_signature='s') def semanage(self, buf): p = Popen(["/usr/sbin/semanage", "import"], stdout=PIPE, stderr=PIPE, stdin=PIPE, universal_newlines=True) p.stdin.write(buf) output = p.communicate() if p.returncode and p.returncode != 0: raise dbus.exceptions.DBusException(output[1]) # # The customized method will return all of the custommizations for policy # on the server. This output can be used with the semanage method on # another server to make the two systems have duplicate policy. # @slip.dbus.polkit.require_auth("org.selinux.customized") @dbus.service.method("org.selinux", in_signature='', out_signature='s') def customized(self): p = Popen(["/usr/sbin/semanage", "export"], stdout=PIPE, stderr=PIPE, universal_newlines=True) buf = p.stdout.read() output = p.communicate() if p.returncode and p.returncode != 0: raise OSError("Failed to read SELinux configuration: %s", output) return buf # # The semodule_list method will return the output of semodule --list=full, using the customized polkit, # since this is a readonly behaviour # @slip.dbus.polkit.require_auth("org.selinux.semodule_list") @dbus.service.method("org.selinux", in_signature='', out_signature='s') def semodule_list(self): p = Popen(["/usr/sbin/semodule", "--list=full"], stdout=PIPE, stderr=PIPE, universal_newlines=True) buf = p.stdout.read() output = p.communicate() if p.returncode and p.returncode != 0: raise OSError("Failed to list SELinux modules: %s", output) return buf # # The restorecon method modifies any file path to the default system label # @slip.dbus.polkit.require_auth("org.selinux.restorecon") @dbus.service.method("org.selinux", in_signature='s') def restorecon(self, path): selinux.restorecon(str(path), recursive=1) # # The setenforce method turns off the current enforcement of SELinux # @slip.dbus.polkit.require_auth("org.selinux.setenforce") @dbus.service.method("org.selinux", in_signature='i') def setenforce(self, value): selinux.security_setenforce(value) # # The setenforce method turns off the current enforcement of SELinux # @slip.dbus.polkit.require_auth("org.selinux.relabel_on_boot") @dbus.service.method("org.selinux", in_signature='i') def relabel_on_boot(self, value): if value == 1: fd = open("/.autorelabel", "w") fd.close() else: os.unlink("/.autorelabel") def write_selinux_config(self, enforcing=None, policy=None): path = selinux.selinux_path() + "config" backup_path = path + ".bck" fd = open(path) lines = fd.readlines() fd.close() fd = open(backup_path, "w") for l in lines: if enforcing and l.startswith("SELINUX="): fd.write("SELINUX=%s\n" % enforcing) continue if policy and l.startswith("SELINUXTYPE="): fd.write("SELINUXTYPE=%s\n" % policy) continue fd.write(l) fd.close() os.rename(backup_path, path) # # The change_default_enforcement modifies the current enforcement mode # @slip.dbus.polkit.require_auth("org.selinux.change_default_mode") @dbus.service.method("org.selinux", in_signature='s') def change_default_mode(self, value): values = ["enforcing", "permissive", "disabled"] if value not in values: raise ValueError("Enforcement mode must be %s" % ", ".join(values)) self.write_selinux_config(enforcing=value) # # The change_default_policy method modifies the policy type # @slip.dbus.polkit.require_auth("org.selinux.change_default_policy") @dbus.service.method("org.selinux", in_signature='s') def change_default_policy(self, value): path = selinux.selinux_path() + value if os.path.isdir(path): return self.write_selinux_config(policy=value) raise ValueError("%s does not exist" % path) if __name__ == "__main__": mainloop = GObject.MainLoop() dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) system_bus = dbus.SystemBus() name = dbus.service.BusName("org.selinux", system_bus) object = selinux_server(system_bus, "/org/selinux/object") slip.dbus.service.set_mainloop(mainloop) mainloop.run() gui/0040755 0000000 0000000 00000000000 13756670063 010411 5ustar000000000 0000000 gui/COPYING0100644 0000000 0000000 00000043131 13756670063 011443 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. gui/Makefile0100644 0000000 0000000 00000004063 13756670063 012051 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin SHAREDIR ?= $(PREFIX)/share/system-config-selinux DATADIR ?= $(PREFIX)/share MANDIR ?= $(PREFIX)/share/man DESKTOPDIR ?= $(PREFIX)/share/applications TARGETS= \ booleansPage.py \ domainsPage.py \ fcontextPage.py \ loginsPage.py \ modulesPage.py \ polgen.ui \ portsPage.py \ semanagePage.py \ statusPage.py \ system-config-selinux.png \ system-config-selinux.ui \ usersPage.py all: $(TARGETS) system-config-selinux.py polgengui.py install: all -mkdir -p $(DESTDIR)$(MANDIR)/man8 -mkdir -p $(DESTDIR)$(SHAREDIR) -mkdir -p $(DESTDIR)$(BINDIR) -mkdir -p $(DESTDIR)$(DATADIR)/pixmaps -mkdir -p $(DESTDIR)$(DATADIR)/icons/hicolor/24x24/apps -mkdir -p $(DESTDIR)$(DATADIR)/polkit-1/actions/ -mkdir -p $(DESTDIR)$(DESKTOPDIR) install -m 755 system-config-selinux.py $(DESTDIR)$(SHAREDIR) install -m 755 system-config-selinux $(DESTDIR)$(BINDIR) install -m 755 polgengui.py $(DESTDIR)$(BINDIR)/selinux-polgengui install -m 644 $(TARGETS) $(DESTDIR)$(SHAREDIR) install -m 644 system-config-selinux.8 $(DESTDIR)$(MANDIR)/man8 install -m 644 selinux-polgengui.8 $(DESTDIR)$(MANDIR)/man8 for lang in $(LINGUAS) ; do \ if [ -e $${lang} ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/man8 ; \ install -m 644 $${lang}/*.8 $(DESTDIR)$(MANDIR)/$${lang}/man8/ ; \ fi ; \ done install -m 644 system-config-selinux.png $(DESTDIR)$(DATADIR)/pixmaps install -m 644 system-config-selinux.png $(DESTDIR)$(DATADIR)/icons/hicolor/24x24/apps install -m 644 system-config-selinux.png $(DESTDIR)$(DATADIR)/system-config-selinux install -m 644 *.desktop $(DESTDIR)$(DESKTOPDIR) -mkdir -p $(DESTDIR)$(DATADIR)/pixmaps install -m 644 sepolicy_256.png $(DESTDIR)$(DATADIR)/pixmaps/sepolicy.png for i in 16 22 32 48 256; do \ mkdir -p $(DESTDIR)$(DATADIR)/icons/hicolor/$${i}x$${i}/apps; \ install -m 644 sepolicy_$${i}.png $(DESTDIR)$(DATADIR)/icons/hicolor/$${i}x$${i}/apps/sepolicy.png; \ done install -m 644 org.selinux.config.policy $(DESTDIR)$(DATADIR)/polkit-1/actions/ clean: indent: relabel: test: gui/VERSION0100644 0000000 0000000 00000000004 13756670063 011450 0ustar000000000 0000000 2.9 gui/booleansPage.py0100644 0000000 0000000 00000017427 13756670063 013372 0ustar000000000 0000000 # # booleansPage.py - GUI for Booleans page in system-config-securitylevel # # Dan Walsh # # Copyright 2006, 2007 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import sys from gi.repository import Gdk, GObject, Gtk import seobject import semanagePage INSTALLPATH = '/usr/share/system-config-selinux' sys.path.append(INSTALLPATH) try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput ENFORCING = 0 PERMISSIVE = 1 DISABLED = 2 ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class Modifier: def __init__(self, name, on, save): self.on = on self.name = name self.save = save def set(self, value): self.on = value self.save = True def isOn(self): return self.on class Boolean(Modifier): def __init__(self, name, val, save=False): Modifier.__init__(self, name, val, save) ACTIVE = 0 MODULE = 1 DESC = 2 BOOLEAN = 3 class booleansPage: def __init__(self, xml, doDebug=None): self.xml = xml self.window = self.xml.get_object("mainWindow").get_root_window() self.local = False self.types = [] self.selinuxsupport = True self.typechanged = False self.doDebug = doDebug self.busy_cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH) self.ready_cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR) # Bring in widgets from glade file. self.booleansFilter = xml.get_object("booleansFilter") self.booleansFilter.connect("focus_out_event", self.filter_changed) self.booleansFilter.connect("activate", self.filter_changed) self.booleansFilter.connect("changed", self.filter_changed) self.booleansView = xml.get_object("booleansView") self.revertButton = xml.get_object("booleanRevertButton") self.revertButton.set_sensitive(self.local) self.revertButton.connect("clicked", self.on_revert_clicked) listStore = Gtk.ListStore(GObject.TYPE_STRING) cell = Gtk.CellRendererText() self.store = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.booleansView.set_model(self.store) checkbox = Gtk.CellRendererToggle() checkbox.connect("toggled", self.boolean_toggled) col = Gtk.TreeViewColumn('Active', checkbox, active=ACTIVE) col.set_clickable(True) col.set_sort_column_id(ACTIVE) self.booleansView.append_column(col) col = Gtk.TreeViewColumn("Module", Gtk.CellRendererText(), text=MODULE) col.set_sort_column_id(MODULE) col.set_resizable(True) self.booleansView.append_column(col) col = Gtk.TreeViewColumn("Description", Gtk.CellRendererText(), text=DESC) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_fixed_width(400) col.set_sort_column_id(DESC) col.set_resizable(True) self.booleansView.append_column(col) col = Gtk.TreeViewColumn("Name", Gtk.CellRendererText(), text=BOOLEAN) col.set_sort_column_id(BOOLEAN) col.set_resizable(True) self.booleansView.set_search_equal_func(self.__search) self.booleansView.append_column(col) self.filter = "" self.load(self.filter) def error(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() dlg.run() dlg.destroy() def __search(self, model, col, key, i): sort_col = self.store.get_sort_column_id()[0] if sort_col > 0: val = model.get_value(i, sort_col) if val.lower().startswith(key.lower()): return False return True def wait(self): self.window.set_cursor(self.busy_cursor) semanagePage.idle_func() def ready(self): self.window.set_cursor(self.ready_cursor) semanagePage.idle_func() def deleteDialog(self): store, iter = self.booleansView.get_selection().get_selected() if iter is None: return boolean = store.get_value(iter, BOOLEAN) # change cursor if boolean is None: return try: self.wait() (rc, out) = getstatusoutput("semanage boolean -d %s" % boolean) self.ready() if rc != 0: return self.error(out) self.load(self.filter) except ValueError as e: self.error(e.args[0]) def filter_changed(self, *arg): filter = arg[0].get_text() if filter != self.filter: self.load(filter) self.filter = filter def use_menus(self): return False def get_description(self): return _("Boolean") def match(self, key, filter=""): try: f = filter.lower() cat = self.booleans.get_category(key).lower() val = self.booleans.get_desc(key).lower() k = key.lower() return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0 except: return False def load(self, filter=None): self.store.clear() self.booleans = seobject.booleanRecords() booleansList = self.booleans.get_all(self.local) for name in booleansList: rec = booleansList[name] if self.match(name, filter): iter = self.store.append() self.store.set_value(iter, ACTIVE, rec[2] == 1) self.store.set_value(iter, MODULE, self.booleans.get_category(name)) self.store.set_value(iter, DESC, self.booleans.get_desc(name)) self.store.set_value(iter, BOOLEAN, name) def boolean_toggled(self, widget, row): iter = self.store.get_iter(row) val = self.store.get_value(iter, ACTIVE) key = self.store.get_value(iter, BOOLEAN) self.store.set_value(iter, ACTIVE, not val) self.wait() setsebool = "/usr/sbin/setsebool -P %s %d" % (key, not val) rc, out = getstatusoutput(setsebool) if rc != 0: self.error(out) self.load(self.filter) self.ready() def on_revert_clicked(self, button): self.wait() setsebool = "semanage boolean --deleteall" getstatusoutput(setsebool) self.load(self.filter) self.ready() def on_local_clicked(self, button): self.local = not self.local self.revertButton.set_sensitive(self.local) if self.local: button.set_label(_("all")) else: button.set_label(_("Customized")) self.load(self.filter) return True gui/domainsPage.py0100644 0000000 0000000 00000012163 13756670063 013212 0ustar000000000 0000000 ## domainsPage.py - show selinux domains ## Copyright (C) 2009 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import os try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput import sys from gi.repository import GObject, Gtk import sepolicy from semanagePage import * ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class domainsPage(semanagePage): def __init__(self, xml): semanagePage.__init__(self, xml, "domains", _("Process Domain")) self.domain_filter = xml.get_object("domainsFilterEntry") self.domain_filter.connect("focus_out_event", self.filter_changed) self.domain_filter.connect("activate", self.filter_changed) self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.view.set_model(self.store) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Domain Name"), Gtk.CellRendererText(), text=0) col.set_sort_column_id(0) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Mode"), Gtk.CellRendererText(), text=1) col.set_sort_column_id(1) col.set_resizable(True) self.view.append_column(col) self.view.get_selection().connect("changed", self.itemSelected) self.permissive_button = xml.get_object("permissiveButton") self.enforcing_button = xml.get_object("enforcingButton") self.domains = sepolicy.get_all_entrypoint_domains() self.load() def get_modules(self): modules = [] fd = os.popen("semodule -l") mods = fd.readlines() fd.close() for l in mods: modules.append(l.split()[0]) return modules def load(self, filter=""): self.filter = filter self.store.clear() try: modules = self.get_modules() for domain in self.domains: if not self.match(domain, filter): continue iter = self.store.append() self.store.set_value(iter, 0, domain) t = "permissive_%s_t" % domain if t in modules: self.store.set_value(iter, 1, _("Permissive")) else: self.store.set_value(iter, 1, "") except: pass self.view.get_selection().select_path((0,)) def itemSelected(self, selection): store, iter = selection.get_selected() if iter is None: return p = store.get_value(iter, 1) == _("Permissive") self.permissive_button.set_sensitive(not p) self.enforcing_button.set_sensitive(p) def deleteDialog(self): # Do nothing return self.delete() def delete(self): selection = self.view.get_selection() store, iter = selection.get_selected() domain = store.get_value(iter, 0) try: self.wait() status, output = getstatusoutput("semanage permissive -d %s_t" % domain) self.ready() if status != 0: self.error(output) else: domain = store.set_value(iter, 1, "") self.itemSelected(selection) except ValueError as e: self.error(e.args[0]) def propertiesDialog(self): # Do nothing return def addDialog(self): # Do nothing return self.add() def add(self): selection = self.view.get_selection() store, iter = selection.get_selected() domain = store.get_value(iter, 0) try: self.wait() status, output = getstatusoutput("semanage permissive -a %s_t" % domain) self.ready() if status != 0: self.error(output) else: domain = store.set_value(iter, 1, _("Permissive")) self.itemSelected(selection) except ValueError as e: self.error(e.args[0]) gui/fcontextPage.py0100644 0000000 0000000 00000020007 13756670063 013406 0ustar000000000 0000000 ## fcontextPage.py - show selinux mappings ## Copyright (C) 2006 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh from gi.repository import GObject, Gtk import seobject try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput from semanagePage import * SPEC_COL = 0 TYPE_COL = 1 FTYPE_COL = 2 class context: def __init__(self, scontext): self.scontext = scontext con = scontext.split(":") self.type = con[0] if len(con) > 1: self.mls = con[1] else: self.mls = "s0" def __str__(self): return self.scontext ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class fcontextPage(semanagePage): def __init__(self, xml): semanagePage.__init__(self, xml, "fcontext", _("File Labeling")) self.fcontextFilter = xml.get_object("fcontextFilterEntry") self.fcontextFilter.connect("focus_out_event", self.filter_changed) self.fcontextFilter.connect("activate", self.filter_changed) self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.view = xml.get_object("fcontextView") self.view.set_model(self.store) self.view.set_search_equal_func(self.search) col = Gtk.TreeViewColumn(_("File\nSpecification"), Gtk.CellRendererText(), text=SPEC_COL) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_fixed_width(250) col.set_sort_column_id(SPEC_COL) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("Selinux\nFile Type"), Gtk.CellRendererText(), text=TYPE_COL) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_fixed_width(250) col.set_sort_column_id(TYPE_COL) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("File\nType"), Gtk.CellRendererText(), text=2) col.set_sort_column_id(FTYPE_COL) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_column_id(SPEC_COL, Gtk.SortType.ASCENDING) self.load() self.fcontextEntry = xml.get_object("fcontextEntry") self.fcontextFileTypeCombo = xml.get_object("fcontextFileTypeCombo") self.fcontextTypeEntry = xml.get_object("fcontextTypeEntry") self.fcontextMLSEntry = xml.get_object("fcontextMLSEntry") def match(self, fcon_dict, k, filter): try: f = filter.lower() for con in k: k = con.lower() if k.find(f) >= 0: return True for con in fcon_dict[k]: k = con.lower() if k.find(f) >= 0: return True except: pass return False def load(self, filter=""): self.filter = filter self.fcontext = seobject.fcontextRecords() self.store.clear() fcon_dict = self.fcontext.get_all(self.local) for k in sorted(fcon_dict.keys()): if not self.match(fcon_dict, k, filter): continue iter = self.store.append() self.store.set_value(iter, SPEC_COL, k[0]) self.store.set_value(iter, FTYPE_COL, k[1]) if fcon_dict[k]: rec = "%s:%s" % (fcon_dict[k][2], seobject.translate(fcon_dict[k][3], False)) else: rec = "<>" self.store.set_value(iter, TYPE_COL, rec) self.view.get_selection().select_path((0,)) def filter_changed(self, *arg): filter = arg[0].get_text() if filter != self.filter: self.load(filter) def dialogInit(self): store, iter = self.view.get_selection().get_selected() self.fcontextEntry.set_text(store.get_value(iter, SPEC_COL)) self.fcontextEntry.set_sensitive(False) scontext = store.get_value(iter, TYPE_COL) scon = context(scontext) self.fcontextTypeEntry.set_text(scon.type) self.fcontextMLSEntry.set_text(scon.mls) type = store.get_value(iter, FTYPE_COL) liststore = self.fcontextFileTypeCombo.get_model() iter = liststore.get_iter_first() while iter != None and liststore.get_value(iter, 0) != type: iter = liststore.iter_next(iter) if iter != None: self.fcontextFileTypeCombo.set_active_iter(iter) self.fcontextFileTypeCombo.set_sensitive(False) def dialogClear(self): self.fcontextEntry.set_text("") self.fcontextEntry.set_sensitive(True) self.fcontextFileTypeCombo.set_sensitive(True) self.fcontextFileTypeCombo.set_active(0) self.fcontextTypeEntry.set_text("") self.fcontextMLSEntry.set_text("s0") def delete(self): store, iter = self.view.get_selection().get_selected() try: fspec = store.get_value(iter, SPEC_COL) ftype = store.get_value(iter, FTYPE_COL) self.wait() (rc, out) = getstatusoutput("semanage fcontext -d -f '%s' '%s'" % (seobject.file_type_str_to_option[ftype], fspec)) self.ready() if rc != 0: return self.error(out) store.remove(iter) self.view.get_selection().select_path((0,)) except ValueError as e: self.error(e.args[0]) def add(self): fspec = self.fcontextEntry.get_text().strip() type = self.fcontextTypeEntry.get_text().strip() mls = self.fcontextMLSEntry.get_text().strip() list_model = self.fcontextFileTypeCombo.get_model() it = self.fcontextFileTypeCombo.get_active_iter() ftype = list_model.get_value(it, 0) self.wait() (rc, out) = getstatusoutput("semanage fcontext -a -t %s -r %s -f '%s' '%s'" % (type, mls, seobject.file_type_str_to_option[ftype], fspec)) self.ready() if rc != 0: self.error(out) return False iter = self.store.append() self.store.set_value(iter, SPEC_COL, fspec) self.store.set_value(iter, FTYPE_COL, ftype) self.store.set_value(iter, TYPE_COL, "%s:%s" % (type, mls)) def modify(self): fspec = self.fcontextEntry.get_text().strip() type = self.fcontextTypeEntry.get_text().strip() mls = self.fcontextMLSEntry.get_text().strip() list_model = self.fcontextFileTypeCombo.get_model() iter = self.fcontextFileTypeCombo.get_active_iter() ftype = list_model.get_value(iter, 0) self.wait() (rc, out) = getstatusoutput("semanage fcontext -m -t %s -r %s -f '%s' '%s'" % (type, mls, seobject.file_type_str_to_option[ftype], fspec)) self.ready() if rc != 0: self.error(out) return False store, iter = self.view.get_selection().get_selected() self.store.set_value(iter, SPEC_COL, fspec) self.store.set_value(iter, FTYPE_COL, ftype) self.store.set_value(iter, TYPE_COL, "%s:%s" % (type, mls)) gui/loginsPage.py0100644 0000000 0000000 00000015515 13756670063 013057 0ustar000000000 0000000 ## loginsPage.py - show selinux mappings ## Copyright (C) 2006 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import sys try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput from gi.repository import GObject, Gtk import seobject from semanagePage import * ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class loginsPage(semanagePage): def __init__(self, xml): self.firstTime = False semanagePage.__init__(self, xml, "logins", _("User Mapping")) self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.view.set_model(self.store) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Login\nName"), Gtk.CellRendererText(), text=0) col.set_sort_column_id(0) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("SELinux\nUser"), Gtk.CellRendererText(), text=1) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("MLS/\nMCS Range"), Gtk.CellRendererText(), text=2) col.set_resizable(True) self.view.append_column(col) self.load() self.loginsNameEntry = xml.get_object("loginsNameEntry") self.loginsSelinuxUserCombo = xml.get_object("loginsSelinuxUserCombo") self.loginsMLSEntry = xml.get_object("loginsMLSEntry") def load(self, filter=""): self.filter = filter self.login = seobject.loginRecords() dict = self.login.get_all(0) self.store.clear() for k in sorted(dict.keys()): range = seobject.translate(dict[k][1]) if not (self.match(k, filter) or self.match(dict[k][0], filter) or self.match(range, filter)): continue iter = self.store.append() self.store.set_value(iter, 0, k) self.store.set_value(iter, 1, dict[k][0]) self.store.set_value(iter, 2, range) self.view.get_selection().select_path((0,)) def __dialogSetup(self): if self.firstTime: return self.firstTime = True liststore = Gtk.ListStore(GObject.TYPE_STRING) self.loginsSelinuxUserCombo.set_model(liststore) cell = Gtk.CellRendererText() self.loginsSelinuxUserCombo.pack_start(cell, True) self.loginsSelinuxUserCombo.add_attribute(cell, 'text', 0) selusers = seobject.seluserRecords().get_all(0) for k in sorted(selusers.keys()): if k != "system_u": self.loginsSelinuxUserCombo.append_text(k) iter = liststore.get_iter_first() while liststore.get_value(iter, 0) != "user_u": iter = liststore.iter_next(iter) self.loginsSelinuxUserCombo.set_active_iter(iter) def dialogInit(self): self.__dialogSetup() store, iter = self.view.get_selection().get_selected() self.loginsNameEntry.set_text(store.get_value(iter, 0)) self.loginsNameEntry.set_sensitive(False) self.loginsMLSEntry.set_text(store.get_value(iter, 2)) seuser = store.get_value(iter, 1) liststore = self.loginsSelinuxUserCombo.get_model() iter = liststore.get_iter_first() while iter != None and liststore.get_value(iter, 0) != seuser: iter = liststore.iter_next(iter) if iter != None: self.loginsSelinuxUserCombo.set_active_iter(iter) def dialogClear(self): self.__dialogSetup() self.loginsNameEntry.set_text("") self.loginsNameEntry.set_sensitive(True) self.loginsMLSEntry.set_text("s0") def delete(self): store, iter = self.view.get_selection().get_selected() try: login = store.get_value(iter, 0) if login == "root" or login == "__default__": raise ValueError(_("Login '%s' is required") % login) self.wait() (rc, out) = getstatusoutput("semanage login -d %s" % login) self.ready() if rc != 0: self.error(out) return False store.remove(iter) self.view.get_selection().select_path((0,)) except ValueError as e: self.error(e.args[0]) def add(self): target = self.loginsNameEntry.get_text().strip() serange = self.loginsMLSEntry.get_text().strip() if serange == "": serange = "s0" list_model = self.loginsSelinuxUserCombo.get_model() iter = self.loginsSelinuxUserCombo.get_active_iter() seuser = list_model.get_value(iter, 0) self.wait() (rc, out) = getstatusoutput("semanage login -a -s %s -r %s %s" % (seuser, serange, target)) self.ready() if rc != 0: self.error(out) return False iter = self.store.append() self.store.set_value(iter, 0, target) self.store.set_value(iter, 1, seuser) self.store.set_value(iter, 2, seobject.translate(serange)) def modify(self): target = self.loginsNameEntry.get_text().strip() serange = self.loginsMLSEntry.get_text().strip() if serange == "": serange = "s0" list_model = self.loginsSelinuxUserCombo.get_model() iter = self.loginsSelinuxUserCombo.get_active_iter() seuser = list_model.get_value(iter, 0) self.wait() (rc, out) = getstatusoutput("semanage login -m -s %s -r %s %s" % (seuser, serange, target)) self.ready() if rc != 0: self.error(out) return False store, iter = self.view.get_selection().get_selected() self.store.set_value(iter, 0, target) self.store.set_value(iter, 1, seuser) self.store.set_value(iter, 2, seobject.translate(serange)) gui/modulesPage.py0100644 0000000 0000000 00000015413 13756670063 013231 0ustar000000000 0000000 ## modulesPage.py - show selinux mappings ## Copyright (C) 2006-2009 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import sys from subprocess import Popen, PIPE try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput from gi.repository import GObject, Gtk import selinux from semanagePage import * ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class modulesPage(semanagePage): def __init__(self, xml): semanagePage.__init__(self, xml, "modules", _("Policy Module")) self.module_filter = xml.get_object("modulesFilterEntry") self.module_filter.connect("focus_out_event", self.filter_changed) self.module_filter.connect("activate", self.filter_changed) self.audit_enabled = False self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.view.set_model(self.store) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Module Name"), Gtk.CellRendererText(), text=0) col.set_sort_column_id(0) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Priority"), Gtk.CellRendererText(), text=1) self.enable_audit_button = xml.get_object("enableAuditButton") self.enable_audit_button.connect("clicked", self.enable_audit) self.new_button = xml.get_object("newModuleButton") self.new_button.connect("clicked", self.new_module) col.set_sort_column_id(1) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_column_id(2, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Kind"), Gtk.CellRendererText(), text=2) col.set_sort_column_id(2) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_func(1, self.sort_int, "") status, self.policy_type = selinux.selinux_getpolicytype() self.load() def sort_int(self, treemodel, iter1, iter2, user_data): try: p1 = int(treemodel.get_value(iter1, 1)) p2 = int(treemodel.get_value(iter1, 1)) if p1 > p2: return 1 if p1 == p2: return 0 return -1 except: return 0 def load(self, filter=""): self.filter = filter self.store.clear() try: fd = Popen("semodule -lfull", shell=True, stdout=PIPE).stdout l = fd.readlines() fd.close() for i in l: priority, module, kind = i.decode('utf-8').split() if not (self.match(module, filter) or self.match(priority, filter)): continue iter = self.store.append() self.store.set_value(iter, 0, module.strip()) self.store.set_value(iter, 1, priority.strip()) self.store.set_value(iter, 2, kind.strip()) except: pass self.view.get_selection().select_path((0,)) def new_module(self, args): try: Popen(["selinux-polgengui"]) except ValueError as e: self.error(e.args[0]) def delete(self): store, iter = self.view.get_selection().get_selected() module = store.get_value(iter, 0) try: self.wait() status, output = getstatusoutput("semodule -r %s" % module) self.ready() if status != 0: self.error(output) else: store.remove(iter) self.view.get_selection().select_path((0,)) except ValueError as e: self.error(e.args[0]) def enable_audit(self, button): self.audit_enabled = not self.audit_enabled try: self.wait() if self.audit_enabled: status, output = getstatusoutput("semodule -DB") button.set_label(_("Disable Audit")) else: status, output = getstatusoutput("semodule -B") button.set_label(_("Enable Audit")) self.ready() if status != 0: self.error(output) except ValueError as e: self.error(e.args[0]) def disable_audit(self, button): try: self.wait() status, output = getstatusoutput("semodule -B") self.ready() if status != 0: self.error(output) except ValueError as e: self.error(e.args[0]) def propertiesDialog(self): # Do nothing return def addDialog(self): dialog = Gtk.FileChooserDialog(_("Load Policy Module"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dialog.set_default_response(Gtk.ResponseType.OK) filter = Gtk.FileFilter() filter.set_name("Policy Files") filter.add_pattern("*.pp") dialog.add_filter(filter) response = dialog.run() if response == Gtk.ResponseType.OK: self.add(dialog.get_filename()) dialog.destroy() def add(self, file): try: self.wait() status, output = getstatusoutput("semodule -i %s" % file) self.ready() if status != 0: self.error(output) else: self.load() except ValueError as e: self.error(e.args[0]) gui/org.selinux.config.policy0100644 0000000 0000000 00000001640 13756670063 015351 0ustar000000000 0000000 System Config SELinux http://fedorahosted.org/system-config-selinux Run System Config SELinux Authentication is required to run system-config-selinux system-selinux no no auth_admin /usr/share/system-config-selinux/system-config-selinux.py true gui/polgen.ui0100644 0000000 0000000 00000422302 13756670063 012234 0ustar000000000 0000000 False 5 normal Red Hat 2007 www.redhat.com GPL Daniel Walsh <dwalsh@redhat.com> translator-credits False False False True end 0 False 12 Add Booleans Dialog mouse 400 dialog True False 6 True False end gtk-cancel True True True False True False False 0 gtk-add True True True False True False False 1 False True end 0 True False 2 2 12 6 True False 0 Boolean Name GTK_FILL True False 0 Description 1 2 GTK_FILL True True False False True True 1 2 True True False False True True 1 2 1 2 True True 1 cancelbutton1 okbutton1 False 5 mouse dialog True True True False 24 True False end gtk-cancel True True True False True False False 0 gtk-add True True True True False True False False 1 False True end 0 button5 button6 True False SELinux Policy Generation Tool True False 18 True False left False True False True False 0 <b>Select the policy type for the application or user role you want to confine:</b> True False False 5 0 True False True False True False 12 True False 6 True False 0 <b>Applications</b> True False False 0 True False True False False False 0 True False 6 Standard Init Daemon True True False Standard Init Daemon are daemons started on boot via init scripts. Usually requires a script in /etc/rc.d/init.d True True False False 0 DBUS System Daemon True True False Standard Init Daemon are daemons started on boot via init scripts. Usually requires a script in /etc/rc.d/init.d True True init_radiobutton False False 1 Internet Services Daemon (inetd) True True False Internet Services Daemon are daemons started by xinetd True True init_radiobutton False False 2 Web Application/Script (CGI) True True False Web Applications/Script (CGI) CGI scripts started by the web server (apache) True True init_radiobutton False False 3 User Application True True False User Application are any application that you would like to confine that is started by a user True True init_radiobutton False False 4 Sandbox True True False User Application are any application that you would like to confine that is started by a user True True init_radiobutton False False 5 False False 1 True True 1 False True 0 True False 6 True False 0 <b>Login Users</b> True False False 0 True False True False False False 0 True False 6 Existing User Roles True True False Modify an existing login user record. True True init_radiobutton False False 0 Minimal Terminal User Role True True False This user will login to a machine only via a terminal or remote login. By default this user will have no setuid, no networking, no su, no sudo. True True init_radiobutton False False 1 Minimal X Windows User Role True True False This user can login to a machine via X or terminal. By default this user will have no setuid, no networking, no sudo, no su True True init_radiobutton False False 2 User Role True True False User with full networking, no setuid applications without transition, no sudo, no su. True True init_radiobutton False False 3 Admin User Role True True False User with full networking, no setuid applications without transition, no su, can sudo to Root Administration Roles True True init_radiobutton False False 4 True False 1 True True 1 False True 1 True False 6 True False 0 <b>Root Users</b> True False False 0 True False True False False False 0 True False Root Admin User Role True True False Select Root Administrator User Role, if this user will be used to administer the machine while running as root. This user will not be able to login to the system directly. True True init_radiobutton False False 0 False False 1 True True 1 True True 2 True True 0 True True 0 True True 1 True False Main Tab False True False True False 0 <b>Enter name of application or user role:</b> True False False 5 0 True False 3 3 12 6 True False 0 Name GTK_FILL True True Enter complete path for executable to be confined. False False True True 1 2 1 2 ... True True False True 2 3 1 2 GTK_FILL True True Enter unique name for the confined application or user role. False False True True 1 3 True False 0 Executable 1 2 GTK_FILL True False 0 Init script 2 3 GTK_FILL True True Enter complete path to init script used to start the confined application. False False True True 1 2 2 3 ... True True False True 2 3 2 3 GTK_FILL True True 1 True False Name Tab 1 False True False True False 0 <b>Select existing role to modify:</b> True False False 5 0 True True automatic automatic in True True Select the user roles that will transiton to the %s domain. False True True 1 True False role tab 2 False True False True False 0 <b>Select roles that %s will transition to:</b> True False False 5 0 True True True True Select applications domains that %s will transition to. False True True 1 True False transition role tab 3 False True False True False 0 <b>Select the user_roles that will transition to %s:</b> True False False 5 0 True True True True Select the user roles that will transiton to this applications domains. False True True 1 True False User Tab 4 False True False True False 0 <b>Select domains that %s will administer:</b> True False False 5 0 True True True True Select the domains that you would like this user administer. False True True 1 True False Admin Tab 5 False True False True False 0 <b>Select additional roles for %s:</b> True False False 5 0 True True True True Select the domains that you would like this user administer. False True True 1 True False Roles Tab 6 False True False True False 0 <b>Enter network ports that %s binds on:</b> True False False 5 0 True False 6 True False 0 <b>TCP Ports</b> True False False 0 True False True False False False 0 True False 6 True False 12 All True True False Allows %s to bind to any udp port True True False False 10 0 600-1024 True True False Allow %s to call bindresvport with 0. Binding to port 600-1024 True True False False 10 1 Unreserved Ports (>1024) True True False Enter a comma separated list of udp ports or ranges of ports that %s binds to. Example: 612, 650-660 True True False False 10 2 True True 0 True False 12 True False 0 Select Ports False False 5 0 True True Allows %s to bind to any udp ports > 1024 False False True True True True 1 True True 1 True True 1 True True 1 True True 1 True False 6 True False 0 <b>UDP Ports</b> True False False 0 True False True False False False 0 True False 6 True False 12 All True True False Allows %s to bind to any udp port True True False False 10 0 600-1024 True True False Allow %s to call bindresvport with 0. Binding to port 600-1024 True True False False 10 1 Unreserved Ports (>1024) True True False Enter a comma separated list of udp ports or ranges of ports that %s binds to. Example: 612, 650-660 True True False False 10 2 True True 0 True False 12 True False 0 Select Ports False False 5 0 True True Allows %s to bind to any udp ports > 1024 False False True True True True 1 True True 1 True True 1 True True 1 True True 2 True False Network Bind tab 7 False True False True False 0 <b>Select network ports that %s connects to:</b> True False False 5 0 True False 6 True False 0 <b>TCP Ports</b> True False False 0 True False True False False False 0 True False 12 All True True False Allows %s to connect to any tcp port True True False False 10 0 True False 0 Select Ports False False 5 1 True True Enter a comma separated list of tcp ports or ranges of ports that %s connects to. Example: 612, 650-660 False False True True True True 2 True True 1 True True 1 True True 1 True False 6 True False 0 <b>UDP Ports</b> True False False 0 True False True False False False 0 True False 12 All True True False Allows %s to connect to any udp port True True False False 10 0 True False 0 Select Ports False False 5 1 True True Enter a comma separated list of udp ports or ranges of ports that %s connects to. Example: 612, 650-660 False False True True True True 2 True True 1 True True 1 True True 2 True False Network Connect Tab 8 False True False True False 0 <b>Select common application traits for %s:</b> True False False 5 0 True False 6 Writes syslog messages True True False True True False False 0 Create/Manipulate temporary files in /tmp True True False True True False False 1 Uses Pam for authentication True True False True True False False 2 Uses nsswitch or getpw* calls True True False True True False False 3 Uses dbus True True False True True False False 4 Sends audit messages True True False True True False False 5 Interacts with the terminal True True False True True False False 6 Sends email True True False True True False False 7 True True 1 True False Common Tab 9 False True False True False 0 <b>Add files/directories that %s manages</b> True False False 5 0 True False 12 True False 6 True True False True False 0 0 True False 2 True False gtk-add False False 0 True False Add File True False False 1 False False 0 True True False True False 0 0 True False 2 True False gtk-add False False 0 True False Add Directory True False False 1 False False 1 gtk-delete True True False True False False 2 False False 4 0 True True automatic automatic in True True Files/Directories which the %s "manages". Pid Files, Log Files, /var/lib Files ... False True True 1 True True 1 True False Add Tab 10 False True False True False 0 <b>Add booleans from the %s policy:</b> True False False 5 0 True False 12 True False 6 True True False True False 0 0 True False 2 True False gtk-add False False 0 True False Add Boolean True False False 1 False False 0 gtk-delete True True False True False False 1 False True 4 0 True True automatic automatic in True True Add/Remove booleans used by the %s domain True True 1 True True 1 True False 11 False True False True False 0 <b>Which directory you will generate the %s policy?</b> True False False 0 True False 12 True False Policy Directory False False 5 0 True True False False True True True True 1 ... True True False True False False 2 False False 12 1 True False 12 False True True 0 True False end gtk-cancel True True True False True False False 0 gtk-go-back True True True False True False False 1 gtk-go-forward True True True False True False False 2 False False 5 1 gui/polgengui.py0100644 0000000 0000000 00000101732 13756670063 012755 0ustar000000000 0000000 #!/usr/bin/python3 -Es # # polgengui.py - GUI for SELinux Config tool in system-config-selinux # # Dan Walsh # # Copyright (C) 2007-2013 Red Hat # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import signal import string import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk import os from gi.repository import GObject import sys try: import sepolicy except ValueError as e: sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) sys.exit(1) import sepolicy.generate import sepolicy.interface try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput import re def get_all_modules(): try: all_modules = [] rc, output = getstatusoutput("semodule -l 2>/dev/null") if rc == 0: l = output.split("\n") for i in l: all_modules.append(i.split()[0]) except: pass return all_modules ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode version = "1.0" sys.path.append('/usr/share/system-config-selinux') sys.path.append('.') # From John Hunter http://www.daa.com.au/pipermail/pygtk/2003-February/004454.html def foreach(model, path, iter, selected): selected.append(model.get_value(iter, 0)) ## ## Pull in the Glade file ## xml = Gtk.Builder() xml.set_translation_domain(PROGNAME) if os.access("polgen.ui", os.F_OK): xml.add_from_file("polgen.ui") else: xml.add_from_file("/usr/share/system-config-selinux/polgen.ui") FILE = 1 DIR = 2 class childWindow: START_PAGE = 0 SELECT_TYPE_PAGE = 0 APP_PAGE = 1 EXISTING_USER_PAGE = 2 TRANSITION_PAGE = 3 USER_TRANSITION_PAGE = 4 ADMIN_PAGE = 5 ROLE_PAGE = 6 IN_NET_PAGE = 7 OUT_NET_PAGE = 8 COMMON_APPS_PAGE = 9 FILES_PAGE = 10 BOOLEAN_PAGE = 11 SELECT_DIR_PAGE = 12 FINISH_PAGE = 12 def __init__(self): self.xml = xml self.notebook = xml.get_object("notebook") self.label_dict = {} self.tooltip_dict = {} label = xml.get_object("select_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_user_roles_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_dir_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_domain_admin_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_in_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_out_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_common_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_manages_label") self.label_dict[label] = label.get_text() label = xml.get_object("select_booleans_label") self.label_dict[label] = label.get_text() label = xml.get_object("existing_user_treeview") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("transition_treeview") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_tcp_all_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_tcp_reserved_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_tcp_unreserved_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_tcp_entry") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_udp_all_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_udp_reserved_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_udp_unreserved_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("in_udp_entry") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("out_tcp_entry") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("out_udp_entry") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("out_tcp_all_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("out_udp_all_checkbutton") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("boolean_treeview") self.tooltip_dict[label] = label.get_tooltip_text() label = xml.get_object("write_treeview") self.tooltip_dict[label] = label.get_tooltip_text() try: self.all_types = sepolicy.generate.get_all_types() self.all_modules = get_all_modules() self.all_roles = sepolicy.generate.get_all_roles() self.all_users = sepolicy.generate.get_all_users() except RuntimeError as e: self.all_types = [] self.all_modules = [] self.all_roles = [] self.all_users = [] self.error(str(e)) self.name = "" handlers = { "on_delete_clicked": self.delete, "on_delete_boolean_clicked": self.delete_boolean, "on_exec_select_clicked": self.exec_select, "on_init_script_select_clicked": self.init_script_select, "on_add_clicked": self.add, "on_add_boolean_clicked": self.add_boolean, "on_add_dir_clicked": self.add_dir, "on_about_clicked": self.on_about_clicked } xml.connect_signals(handlers) xml.get_object("cancel_button").connect("clicked", self.quit) self.forward_button = xml.get_object("forward_button") self.forward_button.connect("clicked", self.forward) self.back_button = xml.get_object("back_button") self.back_button.connect("clicked", self.back) self.boolean_dialog = xml.get_object("boolean_dialog") self.boolean_name_entry = xml.get_object("boolean_name_entry") self.boolean_description_entry = xml.get_object("boolean_description_entry") self.pages = {} for i in sepolicy.generate.USERS: self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.pages[sepolicy.generate.RUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.ADMIN_PAGE, self.USER_TRANSITION_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.pages[sepolicy.generate.LUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.pages[sepolicy.generate.SANDBOX] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.pages[sepolicy.generate.EUSER] = [self.SELECT_TYPE_PAGE, self.EXISTING_USER_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] for i in sepolicy.generate.APPLICATIONS: self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.pages[sepolicy.generate.USER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.USER_TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] self.current_page = 0 self.back_button.set_sensitive(0) self.network_buttons = {} self.in_tcp_all_checkbutton = xml.get_object("in_tcp_all_checkbutton") self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton") self.in_tcp_unreserved_checkbutton = xml.get_object("in_tcp_unreserved_checkbutton") self.in_tcp_entry = self.xml.get_object("in_tcp_entry") self.network_buttons[self.in_tcp_all_checkbutton] = [self.in_tcp_reserved_checkbutton, self.in_tcp_unreserved_checkbutton, self.in_tcp_entry] self.out_tcp_all_checkbutton = xml.get_object("out_tcp_all_checkbutton") self.out_tcp_reserved_checkbutton = xml.get_object("out_tcp_reserved_checkbutton") self.out_tcp_unreserved_checkbutton = xml.get_object("out_tcp_unreserved_checkbutton") self.out_tcp_entry = self.xml.get_object("out_tcp_entry") self.network_buttons[self.out_tcp_all_checkbutton] = [self.out_tcp_entry] self.in_udp_all_checkbutton = xml.get_object("in_udp_all_checkbutton") self.in_udp_reserved_checkbutton = xml.get_object("in_udp_reserved_checkbutton") self.in_udp_unreserved_checkbutton = xml.get_object("in_udp_unreserved_checkbutton") self.in_udp_entry = self.xml.get_object("in_udp_entry") self.network_buttons[self.in_udp_all_checkbutton] = [self.in_udp_reserved_checkbutton, self.in_udp_unreserved_checkbutton, self.in_udp_entry] self.out_udp_all_checkbutton = xml.get_object("out_udp_all_checkbutton") self.out_udp_entry = self.xml.get_object("out_udp_entry") self.network_buttons[self.out_udp_all_checkbutton] = [self.out_udp_entry] for b in self.network_buttons.keys(): b.connect("clicked", self.network_all_clicked) self.boolean_treeview = self.xml.get_object("boolean_treeview") self.boolean_store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.boolean_treeview.set_model(self.boolean_store) self.boolean_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Name"), Gtk.CellRendererText(), text=0) self.boolean_treeview.append_column(col) col = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), text=1) self.boolean_treeview.append_column(col) self.role_treeview = self.xml.get_object("role_treeview") self.role_store = Gtk.ListStore(GObject.TYPE_STRING) self.role_treeview.set_model(self.role_store) self.role_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.role_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Role"), Gtk.CellRendererText(), text=0) self.role_treeview.append_column(col) self.existing_user_treeview = self.xml.get_object("existing_user_treeview") self.existing_user_store = Gtk.ListStore(GObject.TYPE_STRING) self.existing_user_treeview.set_model(self.existing_user_store) self.existing_user_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Existing_User"), Gtk.CellRendererText(), text=0) self.existing_user_treeview.append_column(col) for i in self.all_roles: iter = self.role_store.append() self.role_store.set_value(iter, 0, i[:-2]) self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton") self.transition_treeview = self.xml.get_object("transition_treeview") self.transition_store = Gtk.ListStore(GObject.TYPE_STRING) self.transition_treeview.set_model(self.transition_store) self.transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) self.transition_treeview.append_column(col) self.user_transition_treeview = self.xml.get_object("user_transition_treeview") self.user_transition_store = Gtk.ListStore(GObject.TYPE_STRING) self.user_transition_treeview.set_model(self.user_transition_store) self.user_transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.user_transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) self.user_transition_treeview.append_column(col) for i in self.all_users: iter = self.user_transition_store.append() self.user_transition_store.set_value(iter, 0, i[:-2]) iter = self.existing_user_store.append() self.existing_user_store.set_value(iter, 0, i[:-2]) self.admin_treeview = self.xml.get_object("admin_treeview") self.admin_store = Gtk.ListStore(GObject.TYPE_STRING) self.admin_treeview.set_model(self.admin_store) self.admin_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.admin_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) self.admin_treeview.append_column(col) try: for u in sepolicy.interface.get_user(): iter = self.transition_store.append() self.transition_store.set_value(iter, 0, u) for a in sepolicy.interface.get_admin(): iter = self.admin_store.append() self.admin_store.set_value(iter, 0, a) except ValueError as e: self.error(e.message) def confine_application(self): return self.get_type() in sepolicy.generate.APPLICATIONS def forward(self, arg): type = self.get_type() if self.current_page == self.START_PAGE: self.back_button.set_sensitive(1) if self.pages[type][self.current_page] == self.SELECT_TYPE_PAGE: if self.on_select_type_page_next(): return if self.pages[type][self.current_page] == self.IN_NET_PAGE: if self.on_in_net_page_next(): return if self.pages[type][self.current_page] == self.OUT_NET_PAGE: if self.on_out_net_page_next(): return if self.pages[type][self.current_page] == self.APP_PAGE: if self.on_name_page_next(): return if self.pages[type][self.current_page] == self.EXISTING_USER_PAGE: if self.on_existing_user_page_next(): return if self.pages[type][self.current_page] == self.SELECT_DIR_PAGE: outputdir = self.output_entry.get_text() if not os.path.isdir(outputdir): self.error(_("%s must be a directory") % outputdir) return False if self.pages[type][self.current_page] == self.FINISH_PAGE: self.generate_policy() self.xml.get_object("cancel_button").set_label(Gtk.STOCK_CLOSE) else: self.current_page = self.current_page + 1 self.notebook.set_current_page(self.pages[type][self.current_page]) if self.pages[type][self.current_page] == self.FINISH_PAGE: self.forward_button.set_label(Gtk.STOCK_APPLY) def back(self, arg): type = self.get_type() if self.pages[type][self.current_page] == self.FINISH_PAGE: self.forward_button.set_label(Gtk.STOCK_GO_FORWARD) self.current_page = self.current_page - 1 self.notebook.set_current_page(self.pages[type][self.current_page]) if self.pages[type][self.current_page] == self.START_PAGE: self.back_button.set_sensitive(0) def network_all_clicked(self, button): active = button.get_active() for b in self.network_buttons[button]: b.set_sensitive(not active) def verify(self, message, title=""): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, message) dlg.set_title(title) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() rc = dlg.run() dlg.destroy() return rc def info(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() dlg.run() dlg.destroy() def error(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() dlg.run() dlg.destroy() def get_name(self): if self.existing_user_radiobutton.get_active(): store, iter = self.existing_user_treeview.get_selection().get_selected() if iter == None: raise ValueError(_("You must select a user")) return store.get_value(iter, 0) else: return self.name_entry.get_text() def get_type(self): if self.sandbox_radiobutton.get_active(): return sepolicy.generate.SANDBOX if self.cgi_radiobutton.get_active(): return sepolicy.generate.CGI if self.user_radiobutton.get_active(): return sepolicy.generate.USER if self.init_radiobutton.get_active(): return sepolicy.generate.DAEMON if self.dbus_radiobutton.get_active(): return sepolicy.generate.DBUS if self.inetd_radiobutton.get_active(): return sepolicy.generate.INETD if self.login_user_radiobutton.get_active(): return sepolicy.generate.LUSER if self.admin_user_radiobutton.get_active(): return sepolicy.generate.AUSER if self.xwindows_user_radiobutton.get_active(): return sepolicy.generate.XUSER if self.terminal_user_radiobutton.get_active(): return sepolicy.generate.TUSER if self.root_user_radiobutton.get_active(): return sepolicy.generate.RUSER if self.existing_user_radiobutton.get_active(): return sepolicy.generate.EUSER def generate_policy(self, *args): outputdir = self.output_entry.get_text() try: my_policy = sepolicy.generate.policy(self.get_name(), self.get_type()) iter = self.boolean_store.get_iter_first() while(iter): my_policy.add_boolean(self.boolean_store.get_value(iter, 0), self.boolean_store.get_value(iter, 1)) iter = self.boolean_store.iter_next(iter) if self.get_type() in sepolicy.generate.APPLICATIONS: my_policy.set_program(self.exec_entry.get_text()) my_policy.gen_symbols() my_policy.set_use_syslog(self.syslog_checkbutton.get_active() == 1) my_policy.set_use_tmp(self.tmp_checkbutton.get_active() == 1) my_policy.set_use_uid(self.uid_checkbutton.get_active() == 1) my_policy.set_use_pam(self.pam_checkbutton.get_active() == 1) my_policy.set_use_dbus(self.dbus_checkbutton.get_active() == 1) my_policy.set_use_audit(self.audit_checkbutton.get_active() == 1) my_policy.set_use_terminal(self.terminal_checkbutton.get_active() == 1) my_policy.set_use_mail(self.mail_checkbutton.get_active() == 1) if self.get_type() is sepolicy.generate.DAEMON: my_policy.set_init_script(self.init_script_entry.get_text()) if self.get_type() == sepolicy.generate.USER: selected = [] self.user_transition_treeview.get_selection().selected_foreach(foreach, selected) my_policy.set_transition_users(selected) else: if self.get_type() == sepolicy.generate.RUSER: selected = [] self.admin_treeview.get_selection().selected_foreach(foreach, selected) my_policy.set_admin_domains(selected) selected = [] self.user_transition_treeview.get_selection().selected_foreach(foreach, selected) my_policy.set_transition_users(selected) else: selected = [] self.transition_treeview.get_selection().selected_foreach(foreach, selected) my_policy.set_transition_domains(selected) selected = [] self.role_treeview.get_selection().selected_foreach(foreach, selected) my_policy.set_admin_roles(selected) my_policy.set_in_tcp(self.in_tcp_all_checkbutton.get_active(), self.in_tcp_reserved_checkbutton.get_active(), self.in_tcp_unreserved_checkbutton.get_active(), self.in_tcp_entry.get_text()) my_policy.set_in_udp(self.in_udp_all_checkbutton.get_active(), self.in_udp_reserved_checkbutton.get_active(), self.in_udp_unreserved_checkbutton.get_active(), self.in_udp_entry.get_text()) my_policy.set_out_tcp(self.out_tcp_all_checkbutton.get_active(), self.out_tcp_entry.get_text()) my_policy.set_out_udp(self.out_udp_all_checkbutton.get_active(), self.out_udp_entry.get_text()) iter = self.store.get_iter_first() while(iter): if self.store.get_value(iter, 1) == FILE: my_policy.add_file(self.store.get_value(iter, 0)) else: my_policy.add_dir(self.store.get_value(iter, 0)) iter = self.store.iter_next(iter) self.info(my_policy.generate(outputdir)) return False except ValueError as e: self.error(e.message) def delete(self, args): store, iter = self.view.get_selection().get_selected() if iter != None: store.remove(iter) self.view.get_selection().select_path((0,)) def delete_boolean(self, args): store, iter = self.boolean_treeview.get_selection().get_selected() if iter != None: store.remove(iter) self.boolean_treeview.get_selection().select_path((0,)) def add_boolean(self, type): self.boolean_name_entry.set_text("") self.boolean_description_entry.set_text("") rc = self.boolean_dialog.run() self.boolean_dialog.hide() if rc == Gtk.ResponseType.CANCEL: return iter = self.boolean_store.append() self.boolean_store.set_value(iter, 0, self.boolean_name_entry.get_text()) self.boolean_store.set_value(iter, 1, self.boolean_description_entry.get_text()) def __add(self, type): rc = self.file_dialog.run() self.file_dialog.hide() if rc == Gtk.ResponseType.CANCEL: return for i in self.file_dialog.get_filenames(): iter = self.store.append() self.store.set_value(iter, 0, i) self.store.set_value(iter, 1, type) def exec_select(self, args): self.file_dialog.set_select_multiple(0) self.file_dialog.set_title(_("Select executable file to be confined.")) self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) self.file_dialog.set_current_folder("/usr/sbin") rc = self.file_dialog.run() self.file_dialog.hide() if rc == Gtk.ResponseType.CANCEL: return self.exec_entry.set_text(self.file_dialog.get_filename()) def init_script_select(self, args): self.file_dialog.set_select_multiple(0) self.file_dialog.set_title(_("Select init script file to be confined.")) self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) self.file_dialog.set_current_folder("/etc/rc.d/init.d") rc = self.file_dialog.run() self.file_dialog.hide() if rc == Gtk.ResponseType.CANCEL: return self.init_script_entry.set_text(self.file_dialog.get_filename()) def add(self, args): self.file_dialog.set_title(_("Select file(s) that confined application creates or writes")) self.file_dialog.set_current_folder("/") self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) self.file_dialog.set_select_multiple(1) self.__add(FILE) def add_dir(self, args): self.file_dialog.set_title(_("Select directory(s) that the confined application owns and writes into")) self.file_dialog.set_current_folder("/") self.file_dialog.set_select_multiple(1) self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) self.__add(DIR) def on_about_clicked(self, args): dlg = xml.get_object("about_dialog") dlg.run() dlg.hide() def quit(self, args): Gtk.main_quit() def setupScreen(self): # Bring in widgets from glade file. self.mainWindow = self.xml.get_object("main_window") self.druid = self.xml.get_object("druid") self.type = 0 self.name_entry = self.xml.get_object("name_entry") self.name_entry.connect("insert_text", self.on_name_entry_changed) self.name_entry.connect("focus_out_event", self.on_focus_out_event) self.exec_entry = self.xml.get_object("exec_entry") self.exec_button = self.xml.get_object("exec_button") self.init_script_entry = self.xml.get_object("init_script_entry") self.init_script_button = self.xml.get_object("init_script_button") self.output_entry = self.xml.get_object("output_entry") self.output_entry.set_text(os.getcwd()) self.xml.get_object("output_button").connect("clicked", self.output_button_clicked) self.xwindows_user_radiobutton = self.xml.get_object("xwindows_user_radiobutton") self.terminal_user_radiobutton = self.xml.get_object("terminal_user_radiobutton") self.root_user_radiobutton = self.xml.get_object("root_user_radiobutton") self.login_user_radiobutton = self.xml.get_object("login_user_radiobutton") self.admin_user_radiobutton = self.xml.get_object("admin_user_radiobutton") self.existing_user_radiobutton = self.xml.get_object("existing_user_radiobutton") self.user_radiobutton = self.xml.get_object("user_radiobutton") self.init_radiobutton = self.xml.get_object("init_radiobutton") self.inetd_radiobutton = self.xml.get_object("inetd_radiobutton") self.dbus_radiobutton = self.xml.get_object("dbus_radiobutton") self.cgi_radiobutton = self.xml.get_object("cgi_radiobutton") self.sandbox_radiobutton = self.xml.get_object("sandbox_radiobutton") self.tmp_checkbutton = self.xml.get_object("tmp_checkbutton") self.uid_checkbutton = self.xml.get_object("uid_checkbutton") self.pam_checkbutton = self.xml.get_object("pam_checkbutton") self.dbus_checkbutton = self.xml.get_object("dbus_checkbutton") self.audit_checkbutton = self.xml.get_object("audit_checkbutton") self.terminal_checkbutton = self.xml.get_object("terminal_checkbutton") self.mail_checkbutton = self.xml.get_object("mail_checkbutton") self.syslog_checkbutton = self.xml.get_object("syslog_checkbutton") self.view = self.xml.get_object("write_treeview") self.file_dialog = self.xml.get_object("filechooserdialog") self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT) self.view.set_model(self.store) col = Gtk.TreeViewColumn("", Gtk.CellRendererText(), text=0) col.set_resizable(True) self.view.append_column(col) self.view.get_selection().select_path((0,)) def output_button_clicked(self, *args): self.file_dialog.set_title(_("Select directory to generate policy files in")) self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) self.file_dialog.set_select_multiple(0) rc = self.file_dialog.run() self.file_dialog.hide() if rc == Gtk.ResponseType.CANCEL: return self.output_entry.set_text(self.file_dialog.get_filename()) def on_name_entry_changed(self, entry, text, size, position): if text.find(" ") >= 0: entry.stop_emission_by_name("insert-text") def on_focus_out_event(self, entry, third): name = entry.get_text() if self.name != name: if name in self.all_types: if self.verify(_("Type %s_t already defined in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO: entry.set_text("") return False if name in self.all_modules: if self.verify(_("Module %s already loaded in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO: entry.set_text("") return False file = "/etc/rc.d/init.d/" + name if os.path.isfile(file) and self.init_script_entry.get_text() == "": self.init_script_entry.set_text(file) file = "/usr/sbin/" + name if os.path.isfile(file) and self.exec_entry.get_text() == "": self.exec_entry.set_text(file) self.name = name return False def on_in_net_page_next(self, *args): try: sepolicy.generate.verify_ports(self.in_tcp_entry.get_text()) sepolicy.generate.verify_ports(self.in_udp_entry.get_text()) except ValueError as e: self.error(e.message) return True def on_out_net_page_next(self, *args): try: sepolicy.generate.verify_ports(self.out_tcp_entry.get_text()) sepolicy.generate.verify_ports(self.out_udp_entry.get_text()) except ValueError as e: self.error(e.message) return True def on_select_type_page_next(self, *args): self.exec_entry.set_sensitive(self.confine_application()) self.exec_button.set_sensitive(self.confine_application()) self.init_script_entry.set_sensitive(self.init_radiobutton.get_active()) self.init_script_button.set_sensitive(self.init_radiobutton.get_active()) def on_existing_user_page_next(self, *args): store, iter = self.view.get_selection().get_selected() if iter != None: self.error(_("You must select a user")) return True def on_name_page_next(self, *args): name = self.name_entry.get_text() if not name.isalnum(): self.error(_("You must add a name made up of letters and numbers and containing no spaces.")) return True for i in self.label_dict: text = '%s' % (self.label_dict[i] % ("'" + name + "'")) i.set_markup(text) for i in self.tooltip_dict: text = self.tooltip_dict[i] % ("'" + name + "'") i.set_tooltip_text(text) if self.confine_application(): exe = self.exec_entry.get_text() if exe == "": self.error(_("You must enter a executable")) return True policy = sepolicy.generate.policy(name, self.get_type()) policy.set_program(exe) policy.gen_writeable() policy.gen_symbols() for f in policy.files.keys(): iter = self.store.append() self.store.set_value(iter, 0, f) self.store.set_value(iter, 1, FILE) for f in policy.dirs.keys(): iter = self.store.append() self.store.set_value(iter, 0, f) self.store.set_value(iter, 1, DIR) self.tmp_checkbutton.set_active(policy.use_tmp) self.uid_checkbutton.set_active(policy.use_uid) self.pam_checkbutton.set_active(policy.use_pam) self.dbus_checkbutton.set_active(policy.use_dbus) self.audit_checkbutton.set_active(policy.use_audit) self.terminal_checkbutton.set_active(policy.use_terminal) self.mail_checkbutton.set_active(policy.use_mail) self.syslog_checkbutton.set_active(policy.use_syslog) def stand_alone(self): desktopName = _("Configue SELinux") self.setupScreen() self.mainWindow.connect("destroy", self.quit) self.mainWindow.show_all() Gtk.main() if __name__ == "__main__": signal.signal(signal.SIGINT, signal.SIG_DFL) app = childWindow() app.stand_alone() gui/portsPage.py0100644 0000000 0000000 00000024311 13756670063 012725 0ustar000000000 0000000 ## portsPage.py - show selinux mappings ## Copyright (C) 2006 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import sys from gi.repository import GObject, Gtk import seobject TYPE_COL = 0 PROTOCOL_COL = 1 MLS_COL = 2 PORT_COL = 3 try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput from semanagePage import * ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class portsPage(semanagePage): def __init__(self, xml): semanagePage.__init__(self, xml, "ports", _("Network Port")) group_listview = xml.get_object("listViewButton") group_listview.connect("clicked", self.on_group_clicked) self.group = False self.ports_filter = xml.get_object("portsFilterEntry") self.ports_filter.connect("focus_out_event", self.filter_changed) self.ports_filter.connect("activate", self.filter_changed) self.ports_name_entry = xml.get_object("portsNameEntry") self.ports_protocol_combo = xml.get_object("portsProtocolCombo") self.ports_number_entry = xml.get_object("portsNumberEntry") self.ports_mls_entry = xml.get_object("portsMLSEntry") self.ports_add_button = xml.get_object("portsAddButton") self.ports_properties_button = xml.get_object("portsPropertiesButton") self.ports_delete_button = xml.get_object("portsDeleteButton") liststore = self.ports_protocol_combo.get_model() iter = liststore.get_iter_first() self.ports_protocol_combo.set_active_iter(iter) self.init_store() self.edit = True self.load() def filter_changed(self, *arg): filter = arg[0].get_text() if filter != self.filter: if self.edit: self.load(filter) else: self.group_load(filter) def init_store(self): self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.view.set_model(self.store) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.view.set_search_equal_func(self.search) col = Gtk.TreeViewColumn(_("SELinux Port\nType"), Gtk.CellRendererText(), text=TYPE_COL) col.set_sort_column_id(TYPE_COL) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_column_id(TYPE_COL, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("Protocol"), Gtk.CellRendererText(), text=PROTOCOL_COL) col.set_sort_column_id(PROTOCOL_COL) col.set_resizable(True) self.view.append_column(col) self.mls_col = Gtk.TreeViewColumn(_("MLS/MCS\nLevel"), Gtk.CellRendererText(), text=MLS_COL) self.mls_col.set_resizable(True) self.mls_col.set_sort_column_id(MLS_COL) self.view.append_column(self.mls_col) col = Gtk.TreeViewColumn(_("Port"), Gtk.CellRendererText(), text=PORT_COL) col.set_sort_column_id(PORT_COL) col.set_resizable(True) self.view.append_column(col) self.store.set_sort_func(PORT_COL, self.sort_int, "") def sort_int(self, treemodel, iter1, iter2, user_data): try: p1 = int(treemodel.get_value(iter1, PORT_COL).split('-')[0]) p2 = int(treemodel.get_value(iter2, PORT_COL).split('-')[0]) if p1 > p2: return 1 if p1 == p2: return 0 return -1 except: return 0 def load(self, filter=""): self.filter = filter self.port = seobject.portRecords() dict = self.port.get_all(self.local) self.store.clear() for k in sorted(dict.keys()): if not (self.match(str(k[0]), filter) or self.match(dict[k][0], filter) or self.match(k[2], filter) or self.match(dict[k][1], filter) or self.match(dict[k][1], filter)): continue iter = self.store.append() if k[0] == k[1]: self.store.set_value(iter, PORT_COL, str(k[0])) else: rec = "%s-%s" % k[:2] self.store.set_value(iter, PORT_COL, rec) self.store.set_value(iter, TYPE_COL, dict[k][0]) self.store.set_value(iter, PROTOCOL_COL, k[2]) self.store.set_value(iter, MLS_COL, dict[k][1]) self.view.get_selection().select_path((0,)) def group_load(self, filter=""): self.filter = filter self.port = seobject.portRecords() dict = self.port.get_all_by_type(self.local) self.store.clear() for k in sorted(dict.keys()): ports_string = ", ".join(dict[k]) if not (self.match(ports_string, filter) or self.match(k[0], filter) or self.match(k[1], filter)): continue iter = self.store.append() self.store.set_value(iter, TYPE_COL, k[0]) self.store.set_value(iter, PROTOCOL_COL, k[1]) self.store.set_value(iter, PORT_COL, ports_string) self.store.set_value(iter, MLS_COL, "") self.view.get_selection().select_path((0,)) def propertiesDialog(self): if self.edit: semanagePage.propertiesDialog(self) def dialogInit(self): store, iter = self.view.get_selection().get_selected() self.ports_number_entry.set_text(store.get_value(iter, PORT_COL)) self.ports_number_entry.set_sensitive(False) self.ports_protocol_combo.set_sensitive(False) self.ports_name_entry.set_text(store.get_value(iter, TYPE_COL)) self.ports_mls_entry.set_text(store.get_value(iter, MLS_COL)) protocol = store.get_value(iter, PROTOCOL_COL) liststore = self.ports_protocol_combo.get_model() iter = liststore.get_iter_first() while iter != None and liststore.get_value(iter, 0) != protocol: iter = liststore.iter_next(iter) if iter != None: self.ports_protocol_combo.set_active_iter(iter) def dialogClear(self): self.ports_number_entry.set_text("") self.ports_number_entry.set_sensitive(True) self.ports_protocol_combo.set_sensitive(True) self.ports_name_entry.set_text("") self.ports_mls_entry.set_text("s0") def delete(self): store, iter = self.view.get_selection().get_selected() port = store.get_value(iter, PORT_COL) protocol = store.get_value(iter, 1) try: self.wait() (rc, out) = getstatusoutput("semanage port -d -p %s %s" % (protocol, port)) self.ready() if rc != 0: return self.error(out) store.remove(iter) self.view.get_selection().select_path((0,)) except ValueError as e: self.error(e.args[0]) def add(self): target = self.ports_name_entry.get_text().strip() mls = self.ports_mls_entry.get_text().strip() port_number = self.ports_number_entry.get_text().strip() if port_number == "": port_number = "1" for i in port_number.split("-"): if not i.isdigit(): self.error(_("Port number \"%s\" is not valid. 0 < PORT_NUMBER < 65536 ") % port_number) return False list_model = self.ports_protocol_combo.get_model() iter = self.ports_protocol_combo.get_active_iter() protocol = list_model.get_value(iter, 0) self.wait() (rc, out) = getstatusoutput("semanage port -a -p %s -r %s -t %s %s" % (protocol, mls, target, port_number)) self.ready() if rc != 0: self.error(out) return False iter = self.store.append() self.store.set_value(iter, TYPE_COL, target) self.store.set_value(iter, PORT_COL, port_number) self.store.set_value(iter, PROTOCOL_COL, protocol) self.store.set_value(iter, MLS_COL, mls) def modify(self): target = self.ports_name_entry.get_text().strip() mls = self.ports_mls_entry.get_text().strip() port_number = self.ports_number_entry.get_text().strip() list_model = self.ports_protocol_combo.get_model() iter = self.ports_protocol_combo.get_active_iter() protocol = list_model.get_value(iter, 0) self.wait() (rc, out) = getstatusoutput("semanage port -m -p %s -r %s -t %s %s" % (protocol, mls, target, port_number)) self.ready() if rc != 0: self.error(out) return False store, iter = self.view.get_selection().get_selected() self.store.set_value(iter, TYPE_COL, target) self.store.set_value(iter, PORT_COL, port_number) self.store.set_value(iter, PROTOCOL_COL, protocol) self.store.set_value(iter, MLS_COL, mls) def on_group_clicked(self, button): self.ports_add_button.set_sensitive(self.group) self.ports_properties_button.set_sensitive(self.group) self.ports_delete_button.set_sensitive(self.group) self.mls_col.set_visible(self.group) self.group = not self.group if self.group: button.set_label(_("List View")) self.group_load(self.filter) else: button.set_label(_("Group View")) self.load(self.filter) return True gui/ru/0040755 0000000 0000000 00000000000 13756670063 011037 5ustar000000000 0000000 gui/ru/selinux-polgengui.80100644 0000000 0000000 00000002562 13756670063 014610 0ustar000000000 0000000 .TH "selinux-polgengui" "8" "8 апреля 2013" "Руководство по утилитам настройки системы" .SH ИМЯ selinux\-polgengui \- утилита для создания политики SELinux .SH ОБЗОР .B selinux-polgengui .SH ОПИСАНИЕ \fBselinux-polgengui\fP - графическая утилита, которую можно использовать, чтобы создать платформу для сборки политики SELinux. .SH ПАРАМЕТРЫ Нет .SH ФАЙЛЫ \fi/usr/bin/selinux-polgengui\fP .SH Примеры Чтобы запустить программу, введите: selinux-polgengui .PP .SH "СМОТРИТЕ ТАКЖЕ" .TP selinux(1), sepolicy(8), sepolicy-generate(8) .PP .SH СООБЩЕНИЯ ОБ ОШИБКАХ Отправляйте сообщения об ошибках по адресу . .SH ЛИЦЕНЗИЯ И АВТОРЫ \fBselinux-polgengui\fP распространяется на условиях Стандартной Общественной Лицензии GNU, авторские права принадлежат Red Hat, Inc. .br Эта man-страница была написана Daniel Walsh . Перевод на русский язык выполнила Герасименко Олеся . gui/ru/system-config-selinux.80100644 0000000 0000000 00000002511 13756670063 015400 0ustar000000000 0000000 .TH "system-config-selinux" "8" "8 апреля 2013" "Руководство по утилитам настройки системы" .SH ИМЯ system\-config\-selinux \- утилита для управления SELinux .SH ОБЗОР .B system-config-selinux .SH ОПИСАНИЕ Утилита \fBsystem-config-selinux\fP предоставляет графический интерфейс для управления конфигурацией SELinux. .SH ПАРАМЕТРЫ Нет .SH ФАЙЛЫ \fi/usr/bin/system-config-selinux\fP .SH Примеры Чтобы запустить программу, введите: system-config-selinux .PP .SH "СМОТРИТЕ ТАКЖЕ" .TP selinux(1), semanage(8) .PP .SH СООБЩЕНИЯ ОБ ОШИБКАХ Отправляйте сообщения об ошибках по адресу . .SH ЛИЦЕНЗИЯ И АВТОРЫ \fBsystem-config-selinux\fP распространяется на условиях Стандартной Общественной Лицензии GNU, авторские права принадлежат Red Hat, Inc. .br Эта man-страница была написана Daniel Walsh . Перевод на русский язык выполнила Герасименко Олеся . gui/selinux-polgengui.80100644 0000000 0000000 00000001424 13756670063 014156 0ustar000000000 0000000 .TH "selinux-polgengui" "8" "8 April 2013" "System Config Tools Manual" "System Config Tools Manual" .SH NAME selinux\-polgengui \- SELinux Policy Generation Tool .SH SYNOPSIS .B selinux-polgengui .SH DESCRIPTION \fBselinux-polgengui\fP is a graphical tool, which can be used to create a framework for building SELinux Policy. .SH OPTIONS None .SH FILES \fi/usr/bin/selinux-polgengui\fP .SH Examples To run the program type: selinux-polgengui .PP .SH "SEE ALSO" .TP selinux(1), sepolicy(8), sepolicy-generate(8) .PP .SH REPORTING BUGS Report bugs to . .SH LICENSE AND AUTHORS \fBselinux-polgengui\fP is licensed under the GNU General Public License and is copyrighted by Red Hat, Inc. .br This man page was written by Daniel Walsh gui/selinux-polgengui.desktop0100644 0000000 0000000 00000007336 13756670063 015470 0ustar000000000 0000000 [Desktop Entry] Name=SELinux Policy Generation Tool Name[bn_IN]=SELinux Policy নির্মাণের সামগ্রী Name[ca]=Eina de generació de polítiques del SELinux Name[da]=Regelsætgenereringsværktøj til SELinux Name[de]=Tool zur Erstellung von SELinux-Richtlinien Name[es]=Generador de Políticas de SELinux Name[fi]=SELinux-käytäntöjen generointityökalu Name[fr]=Outil de génération de stratégies SELinux Name[gu]=SELinux પોલિસી બનાવટ સાધન Name[hi]=SELinux पॉलिसी जनन औजार Name[it]=Tool di generazione della policy di SELinux Name[ja]=SELinux ポリシー生成ツール Name[kn]=SELinux ಪಾಲಿಸಿ ಉತ್ಪಾದನಾ ಉಪಕರಣ Name[ko]=SELinux 정책 생성 도구 Name[ml]=SELinux പോളിസി ഉത്പാദന പ്രയോഗം Name[mr]=SELinux करार निर्माण साधन Name[nl]=SELinux tactiek generatie gereedschap Name[or]=SELinux ନୀତି ସୃଷ୍ଟି ଉପକରଣ Name[pa]=SELinux ਪਾਲਿਸੀ ਨਿਰਮਾਣ ਜੰਤਰ Name[pl]=Narzędzie tworzenia polityki SELinuksa Name[pt]=Ferramenta de Geração de Políticas SELinux Name[pt_BR]=Ferramenta de criação de políticas do SELinux Name[ru]=Средство создания политики SELinux Name[sv]=Genereringsverktyg för SELinuxpolicy Name[ta]=SELinux பாலிசி உற்பத்தி கருவி Name[te]=SELinux నిర్వహణ Name[uk]=Утиліта генерації правил SELinux Name[zh_CN]=SELinux 策略生成工具 Name[zh_TW]=SELinux 政策產生工具(SELinux Policy Generation Tool) Comment=Generate SELinux policy modules Comment[bn_IN]=SELinux নিয়মনীতির মডিউল নির্মাণ করুন Comment[ca]=Genera els mòduls de les polítiques de SELinux Comment[da]=Generér SELinux-regelsætmodul Comment[de]=Tool zur Erstellung von SELinux-Richtlinien Comment[es]=Generar módulos de política de SELinux Comment[fi]=Generoi SELinuxin käytäntömoduuleja Comment[fr]=Génére des modules de stratégie SELinux Comment[gu]=SELinux પોલિસી મોડ્યુલોને ઉત્પન્ન કરો Comment[hi]=नया पॉलिसी मॉड्यूल उत्पन्न करें Comment[it]=Genera moduli della politica di SELinux Comment[ja]=新しいポリシーモジュールの作成 Comment[kn]=SELinux ಪಾಲಿಸಿ ಘಟಕಗಳನ್ನು ಉತ್ಪಾದಿಸು Comment[ko]=SELinux 정책 모듈 생성 Comment[ml]=SELinux യ പോളിസി ഘങ്ങള്‍ തയ്യാറാക്കുക Comment[mr]=SELinux करार घटके निर्माण करा Comment[nl]=Maak een SELinux tactiek module aan Comment[or]=SELinux ନୀତି ଏକକାଂଶ ସୃଷ୍ଟିକରନ୍ତୁ Comment[pa]=SELinux ਪਾਲਿਸੀ ਮੈਡਿਊਲ ਬਣਾਓ Comment[pl]=Tworzenie nowych modułów polityki SELinuksa Comment[pt]=Gerar módulos de políticas SELinux Comment[pt_BR]=Gerar módulos de política do SELinux Comment[ru]=Генерация модулей политики SELinux Comment[sv]=Generera SELinux-policymoduler Comment[ta]=SELinux கொள்கை தொகுதியை உருவாக்கவும் Comment[te]=SELinux పాలసీ మాడ్యూళ్ళను వుద్భవింపచేయుము Comment[uk]=Створення модулів контролю доступу SELinux Comment[zh_CN]=生成 SELinux 策略模块 Comment[zh_TW]=產生 SELinux 政策模組 StartupNotify=true Icon=system-config-selinux Exec=/usr/bin/selinux-polgengui Type=Application Terminal=false Categories=System;Security; X-Desktop-File-Install-Version=0.2 gui/semanagePage.py0100644 0000000 0000000 00000012462 13756670063 013342 0ustar000000000 0000000 ## semanagePage.py - show selinux mappings ## Copyright (C) 2006 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import sys from gi.repository import Gdk, Gtk ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode def idle_func(): while Gtk.events_pending(): Gtk.main_iteration() class semanagePage: def __init__(self, xml, name, description): self.xml = xml self.window = self.xml.get_object("mainWindow").get_root_window() self.busy_cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH) self.ready_cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR) self.local = False self.view = xml.get_object("%sView" % name) self.dialog = xml.get_object("%sDialog" % name) self.filter_entry = xml.get_object("%sFilterEntry" % name) self.filter_entry.connect("focus_out_event", self.filter_changed) self.filter_entry.connect("activate", self.filter_changed) self.filter_entry.connect("changed", self.filter_changed) self.view.connect("row_activated", self.rowActivated) self.view.get_selection().connect("changed", self.itemSelected) self.description = description def wait(self): self.window.set_cursor(self.busy_cursor) idle_func() def ready(self): self.window.set_cursor(self.ready_cursor) idle_func() def get_description(self): return self.description def itemSelected(self, selection): return def filter_changed(self, *arg): filter = arg[0].get_text() if filter != self.filter: self.load(filter) def search(self, model, col, key, i): sort_col = self.store.get_sort_column_id()[0] val = model.get_value(i, sort_col) if val.lower().startswith(key.lower()): return False return True def match(self, target, filter): try: f = filter.lower() t = target.lower() if t.find(f) >= 0: return True except: pass return False def rowActivated(self, view, row, Column): self.propertiesDialog() def verify(self, message, title=""): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, message) dlg.set_title(title) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() rc = dlg.run() dlg.destroy() return rc def error(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() dlg.run() dlg.destroy() def deleteDialog(self): store, it = self.view.get_selection().get_selected() if (it is not None) and (self.verify(_("Are you sure you want to delete %s '%s'?" % (self.description, store.get_value(it, 0))), _("Delete %s" % self.description)) == Gtk.ResponseType.YES): self.delete() def use_menus(self): return True def addDialog(self): self.dialogClear() self.dialog.set_title(_("Add %s" % self.description)) self.dialog.set_position(Gtk.WindowPosition.MOUSE) while self.dialog.run() == Gtk.ResponseType.OK: try: if self.add() is False: continue break except ValueError as e: self.error(e.args[0]) self.dialog.hide() def propertiesDialog(self): self.dialogInit() self.dialog.set_title(_("Modify %s" % self.description)) self.dialog.set_position(Gtk.WindowPosition.MOUSE) while self.dialog.run() == Gtk.ResponseType.OK: try: if self.modify() is False: continue break except ValueError as e: self.error(e.args[0]) self.dialog.hide() def on_local_clicked(self, button): self.local = not self.local if self.local: button.set_label(_("all")) else: button.set_label(_("Customized")) self.load(self.filter) return True gui/sepolgen0100644 0000000 0000000 00000000037 13756670063 012145 0ustar000000000 0000000 #!/bin/sh sepolicy generate $* gui/sepolicy.desktop0100644 0000000 0000000 00000000431 13756670063 013626 0ustar000000000 0000000 [Desktop Entry] Name=SELinux Policy Management Tool Comment=Generate SELinux policy modules Icon=sepolicy Exec=/usr/bin/sepolicy gui Type=Application Terminal=false Categories=System;Security; X-Desktop-File-Install-Version=0.2 Keywords=policy;security;selinux;avc;permission;mac; gui/sepolicy_16.png0100644 0000000 0000000 00000002765 13756670063 013263 0ustar000000000 0000000 PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<hiTXtXML:com.adobe.xmp fd#IDATxbd@m-@IhBUeM!0^CC 7ndO#А\0!>|pY0 a4`tF % $(gʊjF A C`$;y3`AJ,`i m]kߊәچ w73xegkbd˱z@6P4W>i30 /3/gy>Ǡj *9]RvDM4H-w e8_>cXpɓ7~#g0J+ IF`.AQώAHR`ZF,p/0{7'~0<"b1@vQp2q3ܼz ̿z0 Im03ϗDH3k[F#r@J]0 r6   q\-E32ʂ ?y' 3`# d뿿d5-\> @h(5 N@t`a ?IENDB`gui/sepolicy_22.png0100644 0000000 0000000 00000003633 13756670063 013253 0ustar000000000 0000000 PNG  IHDRĴl;tEXtSoftwareAdobe ImageReadyqe<hiTXtXML:com.adobe.xmp 5>IDATxڔU_lSe[/]ns]Ge8¢dj\}EhB@^xI 1aY6ddCݶv}nkU;;9s+H(OI- &2D(m"sYE)[Qtsf166NVM%xhzW TJFle$EQJbkť| ek3XlzrJask=>ԺXrS)%$|8:);7~Q/ӡ.(}K \m/O+ _!9E N@[7oxfϮPʬ$T沩pF>{?+ XgT _?,tˏuEcy..j3j4x5%`VS [a$IDATx $gu&zXr%n--k̨%f{`l#!ac7gyfsGdbZ`[hGjm[TwK?ʬʬʪ+EgV.}b-iJ| b-&b-&b-&b-&b-&b-&bmagc=87sѹuoq{ڹO ?vَk/ eȏ@t:T~ S = Qo? KRBZmtO;ۣGR8*]ߏKuFGЧ J \r\;qa?&84 (KP*P*WR.eqH_b蜬2?<< cc;=7=vO]H@w/PF"(JsH8\ &$LJl6 v}a`pZnz|P繷_,1mb^iZPK@Ln7ݻvny{'8  ׇ5n%AJ@ ÆB &I80W\:d2sv=j㑏UG sB_!&X~H 8O@Le~W#Gdc~CCГ7$pT~uJe _#?22oz!ɂ4꼾AHB# /_-)ٙyn‚P `K<}>W\~ {_uA%$)7)RD50C&& )ֿuppַB&irk ^@]X ~Y b0*%y}"(WSs`T iaØ65}[z'2{d!B6}D~}ÁVr ߊ BgM1 l=#pkrd}HR^[xO((  uދY}",ܳɋ{/!2euDm{Nnh9ض)[Gx]IP|ޛ׼(!>>YCcv_7ok$'l_:&-l:)^{ |G;!L%jOz2~AMQ0MM0 ÌCp1+jT"_O{l ?B p l~]){\1׌" v?E(#iFCHލXsIA{- ģM*iݻwd1/u=z@aր9mKpooc bߗxᣂ0}0)B@R!"01`.ާhjV!1e^,E@PVdz4LX\Z G~yR*"* `Ճd'!»bͭ6c^!:w8" y]1SS>3= ϟŅEv!LбܸVnܛS;:jW˳Z1~{kTU7<2"/Mz%d2Yǂ‡ dti< T`2 "~P};W)Rk}?Q> 2CC㿒TՂ>[$@*qLS9뮿!V Ctaij#^!B0 xu7PnX N)ΒnI^7ٗ//=3 &񪡫>dɟJ!X//sy}}$pKnt z$`+~m~opG#;rrţqг;F!4Go uKEknnrG߄#{}F`8/MW2QuR =1dbUcO~}swXy/쓉;KYDV?K/@?nhޕ*y}TT@z;c'& /¹֐ C03lHv|3}{c@yH&5/KUr iwN2^ ޓ;95)8WK{n9w2}<uCmuy~EޗPouŎI b^H%KMHI&POb xž/\djܧWV SQɮ7G'=oO Y|o++ÁdORLR10<1&DΦ\&Pp@bӇ&8''/ɡ>d |&mߐ} w>FծwF V%}Tgu 5zZxt /5H R(HtwzX Xor#ö_܉I7S&aT\>Qړ|,vڷiuCm)q H]ZAn8EF wQ>Z0%S $$h1tb{rxxx/5j3_k#g%\jy-wfBR]߸N}?/?~! w/G`T @BE#@ 7n9l9s#wK̓.&'vtpύMO~0jy{gn))G} T4)M8ZѡhOA||=𞸽xV(hnpP 0+hϙ ~n 'ӭ/}HK~O\M#X.O#|D` &KsTNlqp?3 [Q_ӄn8|D`naŘ'` ܷ }ߌg n?Y$ *>L QK&x k8vk'/?_Y$aVmhʏSgρD~op䐠,-wN7;o]_c1y-KB9ڪB>Àu]@LnGSdR[S{Ύv)yW2%L<[hEPV0`FZSZo 6c) O)_+u{ҲM<'C.vnՏ"y\%¨qh ض?PLkmRPAJpUV.޷zx㢎=G<"zYjX|CuRlg[&U3_(1?uKB>V7XI|{!E*!چmc6h8/Ss{>7X++:8礖 B@x4{Ҡ! `h*PJŒo]u_~cfP g".am@$~"u; ~Rz\ U/'û A8z^rROύ ?&PP QC܊@Q[绦+l |ik+'vݜ>$ ëJ#Г3\oek$+rEs9#Gm!_W}ߵ +mimٷ1HL |_K maMhq#4׌ a:vy&9(\B|c*.j[Bh4X[LȜ+/d!]NN߆Akm]r"U _$zبOK9 ]'l^U)$2@@L $5hF6`ut&SD ~ 6_~P·fAFmq v6 +)JM Bd1 !?z-ޟI l@. f` 2^4;悘zQ^?KX boD>0i:Q^^4͊@ kD (Y[a@ ?MԧϯZj$=I^grгVKc4 Y-)7Wf(!MTPT,c F"bޫ<@]1FZ`(wCYE#.reP6d {τ.wxE-w vC`TIꤿ45  [D "4_ i0oB %c>(|y[zFZD݅|^Oa^(Mw(N-Viv>T?q䙗L1A`BS=X]\3AzZ[-B \Q,8;ܗ fwFз"`p(Xl ;\=DPZ,[{ѤRc` Q+|{Z(P+r' lo]_ KȨIbuЊ OohVFCx9𨾈VqF -P7ŕ_$p6t𙇯o>Q ,~Y O zSc7Za#|'f nh}kDE;/w]g1t_ ?2?Z0 oT#gQ%Pcplcx|׃^!ppk1{^ߌHK1bFAnJ3<D{s,5PO@Og^AtKY~~:/L/o1 9Հ>#;?b}{rȀ0FI%9seDw_5}o9[LmiEaǞBcAK$ W G0B~|]B N$"H1bhBTPwp6n+} +!9{z7"o80 }§gysH֘@+Q ?"Ct/$}[3*`4s/57˔A^>ƒxfGk>쭣 P}m t``D Sk:m׾n14+!qKo!Р! ;grXۼp3^ EG$fS~^I :%RoȐޏ7[@LOe8^FrK$37w$qGGUQ^(̧Γ@2K$\qO/P}EX>^v"r_ĉMU_(a'$h.sO9}l[ <λ8 ;Wː@ 2.NeZuØ>\D;+uI`\}5ZG.3 Fը_m>y~)pomraT0kc9{?ZHG-C2ǣ9B9|9o+m+EPNe25|>o~PUŋ\\m_*٥;`@)JV*NM^߉Ը$jHමjp (?7_m+X$P*av$y}!X,I_9\im 'hiq~ UY+Ujŀb+7$f.KE LW ni+1_ƋҊyt`| Pȗ`a!ayKyf?̏_X*dEqi ~}g$ eD Hb>1nv1~~`̜CtM;2x3mթLk߮QAaXv~Гptà+ec_9"hyxNh ]Cס"RcL!!I@W pdw!dH!xUxK0-dg+]#H(E1$zP/ JzvzCUȶ$!D# v#;#}xLEa"Tz<af/&=),{-|3!IN`L9g<_ M.n\@ 9y6&<$͖l, fGEQk|ZSiu)J>D ((\zgpC}E?hX;<z7EUI<@ǒ~='ضZX op]M ),t/\ Z'WJFP-.R'M? `QZw*?T&c@$V $Ћץ֩ƶ2+ Hf>nONki!.qpCN%s Pv5N' v7coVH$UT*TsY¼3ζ5lxt4&hAv~g%5 ]|O{ڍ 2|e 8 `>q!P@$]IO-gיphe()D0q!w"\y$]ދcǿ wO< WYn+"F 3 é,{q1І%/{ %@x@}Ȧ<#J =9{H-6>l!vlwM$#Lu~#ߖy!I8 פzz]8 q` =I`>_w"p/#rg[!j^׷m-˟!蚝:X|ē݌*`Fs[uE߱ƖS_@3YUQFO$E1u_<~4QNX'ϭ$TIzTxۣz 62<2FB ICn(KMMOTJ?c=z{L9)%& j]iH#HT<$9"j+<$D6Ts cq+F{/&Gɿ:4q D4" ts(6J *R0qciNh4dtھ~U b?j@sgi"&^0*{xo=*%H ^Ȗik6 0m4@*ڥ~iv޻_(/9OGe$`[B ,&tnt'\^vcoJ8q֫"&/!_D2@BD_ʃaRcLM˅@]W_Ϝ @&Ӓmd2b *8F]#02ᜐTu>8}mR#}C;F`s.BQg6(#vIԍB:K:DBT$p:49K55"OØ',,Cyq ]Ёdk9vz?zuz"! 76 ؚ'ӯ0߲싑A&He[od#U+U?|3<|Wxa(꩓^T&iѥ g(\r /$G Pz}JA0`1_ =níoGd"s_ɋHh-=c`ppH;xdMֿh7T N- dMnONˬ+P:̔19xF$oB AAEUs ]L=,*bdHaƖNL9*y?.0‡-RJEsdwؕrFz@*lIJo{7C~"LMs'on}WgoC99eA6!#{ÉI;9pF^c|M»yux$DuA{޾1 9|njj ťq+%b5, {&k"'4y}.Y'8ԲSDP$;0e =&+5 g[Nk?\|Ys^73: {v ùK4*nDtߟ~'֕]o].He>EL.ڄiF=$bh_~;yoz2)%#'I R^ jnPm z" S3?W\zd8uC` B w]{Ku-_F-wчr"{g~C&hnŋxߞ׈L"CbU@ZgcW ><77=?Ap|%L$d 38f!>oq~go?σKqij Ȯ>iif& MbX)؍-m&CeLB? ha҅A};tzc?oo?<P% |'Μ'_8%`/SJss30%%1$I=|ݖe%:thh; ù%ɇ,,CZJ˩d8_ׂDI$0;}!@pi}珠O6 m L&1&,!~0>y|jE2 f{+ݏ u%׻ixTH}mH%8jcΝ:z 2 s$af~^?_uL~1?3]y,ti{~I्K ݡ~6vosp$ H$U? u oq%(&S_ZDڪ@)?u /Z|` /ع]߽ [$yYsiOS(qpN/ y(ߔB^kf yL֝;a.T|v8H݈NvcHR~g'dGATP`'︩IX;4RMCgV '" ׇ upIÄ2T釉 `rzZ1Л.9!$k,* V"UJ4Dc [ŨcP0,9^ݖa3s%f3a5M^X8,O7wz4 h8 O D&|_ sHog+҇$$@M{lʕrBЎBvHmEqi[kwa%qޣ:娋N1JU*v$K]8 myS~'<y1?G n@$Tz$dF0QTS{ܑp &=iӓ+*(d-K y/K&h.^MXYÇrQ1bv~8wZSR(硌MLSDgMk#4`+ ? `o7ùg૧?ۍ8(hV }s7t-$@܁;g;  e·.CFu Ϯڎ?<Y "<%f?cT'eo;w iq™=G <C>K`oqn[1˨(d>d~{_lct0< `'нe:j ߃}/_5x鴭ނjQM_4H'$_2h!o7 %'YiiFn;n+P{+GT\ﭯ^))EoҊ˽;sc< |s'Oם}ㆽ+y{ C fhbE^_4L׿[)MQ6i$aϛǾrO_''yoJgC"*߮2h8k6/_4SƆ7![S| aʁT"CVgu*G2Wc3+oao{T-'޷x#xHe / "ԃh&^_l q,z C`ia#Jb~izejEVQi$;wA1AT?b4ΣGdmB%5WWAZ*=WԪ}HҩT>~5$&&Zk ֊z |*E9߳B Jj]֦XFMI|W :ǃY/,b*26T{y4󛀺Iߜ{W(iT,&˩ۏxPҹQ2 ZML&Vk@˝}@}y(oFDU+Ö곛h@݀9P-$\d^'˪J@IR {:_83ꕇa 1! .;'zj#-.j( !&Bu'WBWj=Wp^UEs7?{XK% żlY.hͨi7!TVk[tv9+~G`з߹ ;Zy+>W pΜ*OD0a ko| | h9 (a)2}78,˰F:*3R!9Q E@On)H:@N P pڋuKG0^oO̹.a:ZqRSMQg=t8n~$b~hKe!Zǁ PBPrPt&W6@aڑ ^tXkP-WnZS."dy vgNIH(Q+ @ktS'exqi~:މۭTJKrN>2jH9C+AdY8lU۱gP|GP-bkO篁? f,[_ &a~g^iM6VH n{ZW̙8߱{qL _O 6$zh2#]UD<#!;Hہhջ:dduieZ\f߇L*j;a`tJN0?$ɣ;R`WE)M p*<%'g_ӢeJ$ >_ O&$O}$хdnuM ( Pٻ{dp *( e_;=|\=U-!vVC}De 7j󐟻(In8cS7{iywxh[}я; F}T@kS^" Cw}7 ˘Ͻ?YW^/X4]8`4ࢫLB“kC]^. "`-@Z/LwnbaZ_O~g-Ln X_.dQ-7J)x.G,ڨ *af##(['3r FyGϟ/<MϹ f6!H!ϖpVST`SHCW#;10<\<8~lNnt?!>)(W8{V$-ra$5&E9Yt!*H ɻN Mry8MD>Ƞ&QL_;=e7w** ]K|uVFf5PŦ"%UV0"JKe,?7&]059ឪۜqrdpH)Gn< -Fy~۲aWoPЭ=n. P;(kְhj_#۶ޱa>K"/.JR+=|;@hiL0Omםq" SD 9@z]#]e6hkX+אTgZXe!*׵[sE}!@ԝXW `=qZ6{ZWqf25®#Y-}vW E(Fh-۶@J}kf4P|Ip~,p}CHIɍ{xXHGS2A!t_GV!@*_]a!Zq4c 0> ؑF vfZ"@LئiFkו@irQN><Rn5@p zr#b6Ѫa@f/^ز@ejKuͪdy&7;)[kx1e)Y!K%o{S )hVKm41)HO1x :{ˌ&5uS;LZ$$ hVÛ'<2ɩ_@*y~0FdJ,S 4q螞xP+jkj$IwgxT$Xm]T 2S% o|>::IfH()WX95~oD=fk `fS#0__W/gCzI4$v9 Z %aגH(f/JC3H.~o!@t @>8#6 #4h9g{@xݾz7y[4\uߕ7QYHm0ilmaM I^naPusmxcYMLtڥ W jC ä*."zDH bqFwȜl') ӵ32Byl ^b{Ls},lT)#bz/\X觡*resҸG>bq8`czӪ2è $1me@ r9A*th{j&-mN ALE[B~<3z*v% Z?edvЯT_Ol]7 IJ)!LJ~,q>t&2+3k6tlԠ :ܐ~N5oz4AZjz" v4&V hMɕEA}SAx E&PS (D @5Ρ+E]Sv=P* H9Ғ#j X\=5AUA ֥sj  19IUv/!I.pщ6seF CU pvy,uƆN"Y\٧W &4wY-aTd -?ُ{oq@< 7&F}ISI-/ yw=ͣS jlIA=\:ti;mNy{2p7Hv ~řTud]--Jpz > |09<fQhvCOء BNȞod^acP = ZJ!Y \t)ϫ1[Q9!RmaYbGuEN߶m`x!59=s S㍖Q9۸O3p1I~C-_os×ɋǨC6,õU ;MllV2'WT+e1'+CPMDhSwat%_L]>K3>t \ᨭ~yRTZ&ې{ke40e2Ѝڨo̲ hLrmTؚs4__Cϟ0M3eVYJzt%shw)mXs썰w/KHu7 H7w2NZ,q,?|0T8Z2B5*i US@!PucxC]N߁_{nRw ^6k?;Gٯ a rʲl ECCg+) ~)24Vߋ 4m F*;q __,U-j,F> `Z.:bj3v38t^'àәR'kKWO1|⇠bOS ?YSN8qB Z\NTJ?c:ȑI@!L/N㗩./W׮P7j|)[Uoˆ qcx ù8TL"H3[I?4ѨPLL?P?66 _"Ņ/(x]" `vzbNe\+fnr,2I +!MK+ir>;z`hh]xQe,KpnAY3)5X+I=>7uȴ} =!h JW.9kw HFhh~~Bcҙ,lnǺxe@ib:0Ǩ.0O `TJ 46P6$b~ۈ7=,L||}>ߝ]3׷Y6x^S;t2#ܐCT1,jAeDnTϡ/RJT?07BA-KǒXjr}}%s@d -:{b;ân4N&FNNZO)r"$So2sâI8{e4qP^jx(M>y0[dnl q"-ϡBX{I@ϳodRQ-Ke S/K1Ep a ?th)-PbaInma''^?\x>D08K'M!*_[.GiBSGVdg5EU `UU1*K?uVVQ/Κ@[RH~{ $CAKʆ$-t]2,QYU*fJb5-)mIaW Stj@GpZ=;n^<|02` T08JSUEdqEX4{'k&̈́퐷bYjr|'ZsgşLn|M'.u@W?nFl{%1ܗrߢֿB"(*Oc*f/y[b\MGqkڗoFEE=4JWK\DK> VRqY5Tt\-!  PE8o5{=?|9VZxŚvADPj/Va|q$9Nރh6_a;@ڑm^ٳ)( uBPAy9e- K:Ve媉r!b *Q?y]+Y@.v*Uʏ{L‹"m7Tu zwQ=k|#RdYQ,ri&VFҟؿ@WJP2Viw /-ԓp+%*yQsĄBUg_+h'glHzR}uSށ;zO=mx8l|!n,-&I7,bC!+4' t&kLF-׏ֵg5{H )#az |d do j2|G~>R+$F ǵ$4nHe}`i%4$?S<mO\YC/I݅3+lS/J,@´yi _Kvgd_N*jQ-RZpr$%h c{[Jbv+&ܔ'O?J:T,EV8O EhPT$p[~x_'p6 K5;S/4 RCYsg;M.^ZfMtn"TnbϵJFY)<\pMb'ɉ|^(@I ae4MISSEOpMǓK5 ITG-mAW^eI̾rsnpaב o8}Nz_nքhBHXodjE_yyU$)th¿%C?=+~Q*ҒxG8=ж ~4 0pPvءAiJN?Va [zi)Lj"`4ɤ"`/S~-1SIվ0ŋZB5qKd~_Z?¡,HJjAo[G2/sTCdߟ'DeVAMg!96  D:<##cǸhY; P%d$uxxXV ~@rb$lA^q^Q5D3UZ*>8 @9干C^ &oQGUi s $a u9¯'F/_W~LtQVtX}oR )gKinmU׹Lr )A… W_mhU |K8v Ν;G?0SFFF\4] DxZ5jGJ4WM>%PN%X^Wd4X._@,s N0Z Ug")X'\+Cmd _ *"{؏k-!RlOXw_;X=jI8 D%@7T2PxM$IX)xf'1 lA (yYVn%UH!PӨxR$ BQF+H.rF  !C9U{ÄD`%:qj3ӿxTDl"QD+JԡUΤa?;xRK=,圮QrQu-%| #z!&2`D1= EƊL3JVA+J}eڬZItT&W[5!OSJ+R1UM￑޳و zvOYaW~-i&J1,qȠ-Ph,p0i&i0 Bݓ06Fx$/K+R!ߺƐW_j}}:z4nYT xU㵔APubTP)T@2t6p8nJSy)q"NmWjnY2"tW28@X`Pp R0GOsES@^XB[P`Q| o?U棏>4X8e1pAHgL!| cQC] NdQt3 ^IpHfZ V7 8׸ H$U=:X 3+ UQ%QF4@l;4hEgA2|h(S$@NuaOV- URmkz#+OIAB1$pFLEkEǰVS1^|9S4 naTq3Pu Lo-S97<-eKt[Ғ^1JC"5EHU*2n`(''s[2Lq/jСlISSD'* #l6Ţ68ww&_ֱ(ɁrAlpVgN)~GnSpdXFui_g]/ %FUj@u+rrǨ$ t0Uje~Z2 KR0brh#z=WP|eEQ= r_x%Imq4ڢ$ 0*KcmeH&]4*Wm.4VA*aRTnJvTei4N_Ua8@jd}q() PW.թW. 6HQp 48渚RQ_2 \!?rZP!&ʨ(UܓbQï 䄈 ժ?bbŦ9Us^5 Wբ"0fetZTRT/~[<84 #[JaAU kCV$C9_ѽ}ϗFQ!IįaM"4QyM $ZPg*I$Ra7J0VBV("ST< Ue& ;Rbk5#s7x((ċ*UZC늁H/!\!9c^h$eO ^à[$iX]rfSXمLv ٜj\뙔HsOIǦA-kkrr.ªs[L#LR:.Y`0P2e0gT,%DZ[U Xɨ`-jޟFk1zђ : i@BU%] c.1-y꣏QIE@<2їEI+*STDR nb$ȪCJ4=رc b0@155%欽{|>/PeSZ4eE"gi[cPzvJ ؓL$C+Pk."7d4MtIUܘFwVӜg]KFB'K cJ9"&9'[/4 ,GhZ~ G"hb[;Tof{(?kA9d2RUVi(UVIP2 5 tĥB~SOzFDG)TL;4eITe~e MʉQI&bjQܡ?K۷o>"cc4MAiÇe958q1@׍S(/JXiyz"Յԋb\.ScaP2g0b ?{#4ݢ z5IS arASw),xs)knAv ZIGbmYWl[l[lm)ɪgIENDB`gui/sepolicy_32.png0100644 0000000 0000000 00000004756 13756670063 013263 0ustar000000000 0000000 PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<hiTXtXML:com.adobe.xmp &IDATxڬW[lUfvvvVR!KhB !MMx@_ј`%.m:;N)-Os朝;0|Avvzm[1۶niѰGUUB eŽT*^S ]wF7?Y?+ 2MBj(QJ}ka2]& o{/nGFq#IF"@SS#i2sp( ϟP ݳ@2Z ?=>]1UVB#\2IǞz( Zrq~/h= Jb͒}yQsqv#aw#_9#|C&:J=ys߰Zv :BgڍGYM(n7XsKY83|>D"7z՚Z!P`:wYơt|q}Og/ְƠe9 OB)3vVqIJN7P2p>A HY @Tb7cI^P7DChN=(tHc0VnpV3H)'!+flHJ>O!lڙK.d3ɧ~Pgfd^߻P #q #.=j>Ѷ#E,R[G{-ԝ Q?BwNAhޘ4<\hC'UNZ#.dFNny089Ε;c-60JB0F a IDATxZ[l沗]ƎbCA ҖHPQ[ATJ}+AZ J4Q4 Mszsٝٛ N"N{vϜ3}翞\WI2鷿{n.[I<)oHϋ/]%tyu:464gF'J|2\/"WE3=[zhaMs, mϲ$#9ĉ1YHi<;88AUTشL&4  Dpq3˭ & /fӷzWvfBU6r|Ax0ߟKa`V-{0fi}E f`ɹYCP(I*( e2h11;aeY%Yf!M#"VkBuc^blYZѳ8{훅>cP|IWm|peZ}6MNL1_(4籉ɞvADR.G4L?0Dbo}\chu8д0o] n2+O`Qz% r{8޽+i\E;?oBx/X.rM7=7}\Yǩx4bb*Trģ"euq1'RbK!D6oy Ѻ6"˾ÇyeUUY h IͥDU} '@T]AU!34qCC!~g?=^募vY`3^\#eH;i@ D2mN}̧/>#^ >JdF#7wʗ7r[噍Yh?|وO-7hf!wF1خ.I#"3 .82$o^~$sM6c|.B3 G:m@}K;Z$fB2e=Nw׊f7s):tla- wmGc0` qZt̻mѤoY63TD<[O%.1rXH@ы[ĦPh*Ӯi氊a?o<=r^ Q'G6DkS$']MP%J9nh-@NJvTdipme2s:ikWP֐\ˁmٴG+ϟmNV8o~ [nuH)mD\1x-Re/E^Kq ]s$&$E%..<Ȧ+ RTqj٢dm3}oХE |l\L=n@|fPtrlNlաUOJ(d`Ea~~8bf"Z9x0cVumsr??y XdNpX $ }S"*+|iAl9XL~3d~l~AwRZL nIaI)j` K nYP&G,+ V33C8EdU<7HֲP-DhGTc! Y*LsdWRrgY,Y{[tE򂇸YtISFч%+wDN1HN,CR/u&~$m5"5@-b4Mw>XcJQhNOxWrw|}|6 T;A5lg* Ko.$Z}xoDxMMzц5JN ^ ԗWjre4JYWݯ &5ɟ 0lL@D.>4hSGRg; 9i2g9yA8PyY ?M܉d])Cb%3r'E6)*ܹFB: )'Zeݺs||!l2w਴t]υX g̹%\v}{п5esn Vlf'!1~Np^ Uْq }kΓǪÞ;t% ƽH>[ޜ c?u]oϿfRjWAeV_R`` m'3IENDB`gui/statusPage.py0100644 0000000 0000000 00000017114 13756670063 013104 0ustar000000000 0000000 # statusPage.py - show selinux status ## Copyright (C) 2006-2009 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import os import sys from gi.repository import Gtk import selinux INSTALLPATH = '/usr/share/system-config-selinux' sys.path.append(INSTALLPATH) ENFORCING = 1 PERMISSIVE = 0 DISABLED = -1 modearray = ("disabled", "permissive", "enforcing") SELINUXDIR = "/etc/selinux/" RELABELFILE = "/.autorelabel" ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class statusPage: def __init__(self, xml): self.xml = xml self.needRelabel = False self.type = selinux.selinux_getpolicytype() # Bring in widgets from glade file. self.selinuxTypeOptionMenu = xml.get_object("selinuxTypeOptionMenu") self.typeLabel = xml.get_object("typeLabel") self.enabledOptionMenu = xml.get_object("enabledOptionMenu") self.currentOptionMenu = xml.get_object("currentOptionMenu") self.relabel_checkbutton = xml.get_object("relabelCheckbutton") self.relabel_checkbutton.set_active(self.is_relabel()) self.relabel_checkbutton.connect("toggled", self.on_relabel_toggle) if self.get_current_mode() == ENFORCING or self.get_current_mode() == PERMISSIVE: self.currentOptionMenu.append_text(_("Permissive")) self.currentOptionMenu.append_text(_("Enforcing")) self.currentOptionMenu.set_active(self.get_current_mode()) self.currentOptionMenu.connect("changed", self.set_current_mode) self.currentOptionMenu.set_sensitive(True) else: self.currentOptionMenu.append_text(_("Disabled")) self.currentOptionMenu.set_active(0) self.currentOptionMenu.set_sensitive(False) if self.read_selinux_config() is None: self.selinuxsupport = False else: self.enabledOptionMenu.connect("changed", self.enabled_changed) # # This line must come after read_selinux_config # self.selinuxTypeOptionMenu.connect("changed", self.typemenu_changed) self.typeLabel.set_mnemonic_widget(self.selinuxTypeOptionMenu) def use_menus(self): return False def get_description(self): return _("Status") def get_current_mode(self): if selinux.is_selinux_enabled(): if selinux.security_getenforce() > 0: return ENFORCING else: return PERMISSIVE else: return DISABLED def set_current_mode(self, menu): selinux.security_setenforce(menu.get_active() == 1) def is_relabel(self): return os.access(RELABELFILE, os.F_OK) != 0 def on_relabel_toggle(self, button): if button.get_active(): fd = open(RELABELFILE, "w") fd.close() else: if os.access(RELABELFILE, os.F_OK) != 0: os.unlink(RELABELFILE) def verify(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() rc = dlg.run() dlg.destroy() return rc def typemenu_changed(self, menu): type = self.get_type() enabled = self.enabledOptionMenu.get_active() if self.initialtype != type: if self.verify(_("Changing the policy type will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system. Do you wish to continue?")) == Gtk.ResponseType.NO: menu.set_active(self.typeHistory) return None self.relabel_checkbutton.set_active(True) self.write_selinux_config(modearray[enabled], type) self.typeHistory = menu.get_active() def enabled_changed(self, combo): enabled = combo.get_active() type = self.get_type() if self.initEnabled != DISABLED and enabled == DISABLED: if self.verify(_("Changing to SELinux disabled requires a reboot. It is not recommended. If you later decide to turn SELinux back on, the system will be required to relabel. If you just want to see if SELinux is causing a problem on your system, you can go to permissive mode which will only log errors and not enforce SELinux policy. Permissive mode does not require a reboot Do you wish to continue?")) == Gtk.ResponseType.NO: combo.set_active(self.enabled) return None if self.initEnabled == DISABLED and enabled < 2: if self.verify(_("Changing to SELinux enabled will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system. Do you wish to continue?")) == Gtk.ResponseType.NO: combo.set_active(self.enabled) return None self.relabel_checkbutton.set_active(True) self.write_selinux_config(modearray[enabled], type) self.enabled = enabled def write_selinux_config(self, enforcing, type): path = selinux.selinux_path() + "config" backup_path = path + ".bck" fd = open(path) lines = fd.readlines() fd.close() fd = open(backup_path, "w") for l in lines: if l.startswith("SELINUX="): fd.write("SELINUX=%s\n" % enforcing) continue if l.startswith("SELINUXTYPE="): fd.write("SELINUXTYPE=%s\n" % type) continue fd.write(l) fd.close() os.rename(backup_path, path) def read_selinux_config(self): self.initialtype = selinux.selinux_getpolicytype()[1] try: self.initEnabled = selinux.selinux_getenforcemode()[1] except: self.initEnabled = False pass self.enabled = self.initEnabled self.enabledOptionMenu.set_active(self.enabled + 1) self.types = [] n = 0 current = n for i in os.listdir(SELINUXDIR): if os.path.isdir(SELINUXDIR + i) and os.path.isdir(SELINUXDIR + i + "/policy"): self.types.append(i) self.selinuxTypeOptionMenu.append_text(i) if i == self.initialtype: current = n n = n + 1 self.selinuxTypeOptionMenu.set_active(current) self.typeHistory = current return 0 def get_type(self): return self.types[self.selinuxTypeOptionMenu.get_active()] gui/system-config-selinux0100755 0000000 0000000 00000000132 13756670063 014604 0ustar000000000 0000000 #!/bin/sh exec /usr/bin/pkexec /usr/share/system-config-selinux/system-config-selinux.py gui/system-config-selinux.80100644 0000000 0000000 00000001402 13756670063 014750 0ustar000000000 0000000 .TH "system-config-selinux" "8" "8 April 2013" "System Config Tools Manual" "System Config Tools Manual" .SH NAME system\-config\-selinux \- SELinux Management tool .SH SYNOPSIS .B system-config-selinux .SH DESCRIPTION \fBsystem-config-selinux\fP provides a graphical interface for managing the SELinux configuration. .SH OPTIONS None .SH FILES \fi/usr/bin/system-config-selinux\fP .SH Examples To run the program type: system-config-selinux .PP .SH "SEE ALSO" .TP selinux(1), semanage(8) .PP .SH REPORTING BUGS Report bugs to . .SH LICENSE AND AUTHORS \fBsystem-config-selinux\fP is licensed under the GNU General Public License and is copyrighted by Red Hat, Inc. .br This man page was written by Daniel Walsh gui/system-config-selinux.desktop0100644 0000000 0000000 00000007010 13756670063 016253 0ustar000000000 0000000 [Desktop Entry] Name=SELinux Management Name[bn_IN]=SELinux পরিচালনা Name[da]=Håndtering af SELinux Name[de]=SELinux-Management Name[ca]=Gestió de SELinux Name[es]=Administración de SELinux Name[fi]=SELinuxin ylläpito Name[fr]=Gestion de SELinux Name[gu]=SELinux સંચાલન Name[hi]=SELinux प्रबंधन Name[jp]=SELinux 管理 Name[it]=Gestione di SELinux Name[kn]=SELinux ವ್ಯವಸ್ಥಾಪನೆ Name[ko]=SELinux 관리 Name[ml]=SELinux മാനേജ്മെന്റ് Name[mr]=SELinux मॅनेजमेंट Name[nl]=SELinux beheer Name[or]=SELinux ପରିଚାଳନା Name[pa]=SELinux ਮੈਨੇਜਮੈਂਟ Name[pl]=Zarządzanie SELinuksem Name[pt_BR]=Gerenciamento do SELinux Name[pt]=Gestão de SELinux Name[ru]=Управление SELinux Name[sv]=SELinux-hantering Name[ta]=SELinux மேலாண்மை Name[te]=SELinux నిర్వహణ Name[uk]=Керування SELinux Name[zh_CN]=SELinux 管理 Name[zh_TW]=SELinux 管理 Comment=Configure SELinux in a graphical setting Comment[bn_IN]=গ্রাফিক্যাল পরিবেশে SELinux কনফিগার করুন Comment[ca]=Configura SELinuc an mode de preferències gràfiques Comment[da]=Konfigurér SELinux i et grafisk miljø Comment[de]=SELinux in einer grafischen Einstellung konfigurieren Comment[es]=Defina SELinux en una configuración de interfaz gráfica Comment[fi]=Tee SELinuxin asetukset graafisesti Comment[fr]=Configure SELinux dans un environnement graphique Comment[gu]=ગ્રાફિકલ સુયોજનમાં SELinux ને રૂપરેખાંકિત કરો Comment[hi]=SELinux को आलेखी सेटिंग में विन्यस्त करें Comment[it]=Configura SELinux in una impostazione grafica Comment[jp]=グラフィカルな設定画面で SELinux を設定する Comment[ko]=SELinux를 그래픽 사용자 인터페이스로 설정 Comment[kn]=SELinux ಅನ್ನು ಒಂದು ಚಿತ್ರಾತ್ಮಕ ಸಿದ್ದತೆಯಲ್ಲಿ ಸಂರಚಿಸಿ Comment[ml]=ഒരു ഗ്രാഫിക്കല്‍ സജ്ജീകരണത്തില്‍ SELinux ക്രമീകരിയ്ക്കുക Comment[mr]=ग्राफिकल सेटिंगमध्ये SELinux संरचीत करा Comment[nl]=Configureer SELinux in een grafische omgeving Comment[or]=SELinux କୁ ଆଲେଖିକ ସଂରଚନାରେ ବିନ୍ୟାସ କରନ୍ତୁ Comment[pa]=SELinux ਨੂੰ ਗਰਾਫੀਕਲ ਸੈਟਿੰਗ ਵਿੱਚ ਸੰਰਚਿਤ ਕਰੋ Comment[pl]=Konfiguracja SELinuksa w trybie graficznym Comment[pt]=Configurar o SELinux num ambiente gráfico Comment[pt_BR]=Configure o SELinux em uma configuração gráfica Comment[ru]=Настройка SELinux в графическом режиме Comment[sv]=Konfigurera SELinux i en grafisk miljö Comment[ta]=SELinuxஐ ஒரு வரைகலை அமைவில் கட்டமைக்கவும் Comment[te]=SELinuxను గ్రాఫికల్ అమర్పునందు ఆకృతీకరించుము Comment[uk]=Засіб для налаштування SELinux з графічним інтерфейсом Comment[zh_CN]=在图形设置中配置 SELinux Comment[zh_TW]=在圖形話設定中配置 SELinux StartupNotify=true Icon=system-config-selinux Exec=/usr/bin/system-config-selinux Type=Application Terminal=false Categories=System;Security; X-Desktop-File-Install-Version=0.2 gui/system-config-selinux.png0100644 0000000 0000000 00000002647 13756670063 015401 0ustar000000000 0000000 PNG  IHDRw=gAMAOX2tEXtSoftwareAdobe ImageReadyqe<9IDATxڴV]Lg~c6Bafe2;B˂f2pKŒ-xKHlKAb6Q.J2)VZJ|mfٲ{=9梅1:L;ppKKKo@"l۶aV#LeZ<Nu9Ӊp87nAZp5t bmMg'k]?~|~D"bff&C L x\h|1?Z A6!pu U@mGyx[)kb߾}P(P"T*UΩd³Ph<+iB!},LSn:ŒYRYlCaTjD[[ԙDGN%0K'޹&q( i \ -,mLc*yÓC_m`!I5>="RaΝ]!D `dT_ jH g8:2xƕ@8TVVI;(ZA%q║i2iBnb_lX6V455l`]6*o>g7ʕT*tyTP;D7oc100z466H055(+FN*\BOٞ!LBxScISH^۵ΝU%IgmDђBح! M؎L/˚q!S v/c8&N+Vhd2aǎbN***x0pF>z1ޘ*8߾?Ut;{oe/ʖTljet V]] KXoVIU;h0>'ۄ@}2/%E($/_/x%I;-!^~IENDB`gui/system-config-selinux.py0100644 0000000 0000000 00000014174 13756670063 015243 0ustar000000000 0000000 #!/usr/bin/python3 -Es # # system-config-selinux.py - GUI for SELinux Config tool in system-config-selinux # # Dan Walsh # # Copyright 2006-2009 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # import os import signal import sys import gi gi.require_version('Gtk', '3.0') try: from gi.repository import Gtk except RuntimeError as e: print("system-config-selinux:", e) print("This is a graphical application and requires DISPLAY to be set.") sys.exit(1) from gi.repository import GObject import statusPage import booleansPage import loginsPage import usersPage import portsPage import modulesPage import domainsPage import fcontextPage import selinux ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode version = "1.0" sys.path.append('/usr/share/system-config-selinux') ## ## Pull in the Glade file ## xml = Gtk.Builder() xml.set_translation_domain(PROGNAME) if os.access("system-config-selinux.ui", os.F_OK): xml.add_from_file("system-config-selinux.ui") else: xml.add_from_file("/usr/share/system-config-selinux/system-config-selinux.ui") class childWindow: def __init__(self): self.tabs = [] self.xml = xml xml.connect_signals({ "on_quit_activate": self.destroy, "on_delete_clicked": self.delete, "on_add_clicked": self.add, "on_properties_clicked": self.properties, "on_local_clicked": self.on_local_clicked, "on_policy_activate": self.policy, "on_logging_activate": self.logging, "on_about_activate": self.on_about_activate, }) self.add_page(statusPage.statusPage(xml)) if selinux.is_selinux_enabled() > 0: try: self.add_page(booleansPage.booleansPage(xml)) self.add_page(fcontextPage.fcontextPage(xml)) self.add_page(loginsPage.loginsPage(xml)) self.add_page(usersPage.usersPage(xml)) self.add_page(portsPage.portsPage(xml)) self.add_page(modulesPage.modulesPage(xml)) # modules self.add_page(domainsPage.domainsPage(xml)) # domains except ValueError as e: self.error(e.message) self.add_menu = xml.get_object("add_menu_item") self.properties_menu = xml.get_object("properties_menu_item") self.delete_menu = xml.get_object("delete_menu_item") def error(self, message): dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, message) dlg.set_position(Gtk.WindowPosition.MOUSE) dlg.show_all() dlg.run() dlg.destroy() def add_page(self, page): self.tabs.append(page) def policy(self, args): os.spawnl(os.P_NOWAIT, "/usr/share/system-config-selinux/semanagegui.py") def logging(self, args): os.spawnl(os.P_NOWAIT, "/usr/bin/seaudit") def delete(self, args): self.tabs[self.notebook.get_current_page()].deleteDialog() def add(self, args): self.tabs[self.notebook.get_current_page()].addDialog() def properties(self, args): self.tabs[self.notebook.get_current_page()].propertiesDialog() def on_local_clicked(self, button): self.tabs[self.notebook.get_current_page()].on_local_clicked(button) def on_about_activate(self, args): dlg = xml.get_object("aboutWindow") dlg.run() dlg.hide() def destroy(self, args): Gtk.main_quit() def use_menus(self, use_menus): self.add_menu.set_sensitive(use_menus) self.properties_menu.set_sensitive(use_menus) self.delete_menu.set_sensitive(use_menus) def itemSelected(self, selection): store, rows = selection.get_selected_rows() if store != None and len(rows) > 0: self.notebook.set_current_page(rows[0][0]) self.use_menus(self.tabs[rows[0][0]].use_menus()) else: self.notebook.set_current_page(0) self.use_menus(self.tabs[0].use_menus()) def setupScreen(self): # Bring in widgets from glade file. self.mainWindow = self.xml.get_object("mainWindow") self.notebook = self.xml.get_object("notebook") self.view = self.xml.get_object("selectView") self.view.get_selection().connect("changed", self.itemSelected) self.store = Gtk.ListStore(GObject.TYPE_STRING) self.view.set_model(self.store) col = Gtk.TreeViewColumn("", Gtk.CellRendererText(), text=0) col.set_resizable(True) self.view.append_column(col) for page in self.tabs: iter = self.store.append() self.store.set_value(iter, 0, page.get_description()) self.view.get_selection().select_path((0,)) def stand_alone(self): desktopName = _("Configue SELinux") self.setupScreen() self.mainWindow.connect("destroy", self.destroy) self.mainWindow.show_all() Gtk.main() if __name__ == "__main__": signal.signal(signal.SIGINT, signal.SIG_DFL) app = childWindow() app.stand_alone() gui/system-config-selinux.ui0100644 0000000 0000000 00000311254 13756670063 015227 0ustar000000000 0000000 system-config-selinux False 5 normal Copyright (c)2006 Red Hat, Inc. Copyright (c) 2006 Dan Walsh <dwalsh@redhat.com> Daniel Walsh <dwalsh@redhat.com> translator-credits system-config-selinux.png False False False False 0 True False gtk-add True False gtk-properties True False gtk-delete False Add SELinux Login Mapping dialog True False True False end gtk-cancel True True True False True True True 0 gtk-ok True True True False True True True 1 False True end 0 True False vertical True False 4 6 True False Login Name 0 0 True False SELinux User 0 1 True False MLS/MCS Range 0 2 True True * 1 0 True False 1 1 True True * 1 2 True True 5 0 True True 1 cancelbutton1 okbutton1 tcp udp False Add SELinux Network Ports dialog True False True False end gtk-cancel True True True False True True True 0 gtk-ok True True True False True True True 1 False True end 0 True False vertical True False 4 6 True False Port Number 0 0 True False Protocol 0 1 True False SELinux Type 0 2 True True * 1 0 True False model1 0 1 1 True True * 1 2 True False MLS/MCS Level 0 3 True True * 1 3 True True 5 0 True True 1 button1 button2 all files regular file directory character device block device socket file symbolic link named pipe False Add SELinux Login Mapping dialog True False True False end gtk-cancel True True True False True True True 0 gtk-ok True True True False True True True 1 False True end 0 True False vertical True False 4 6 True False File Specification 0 0 True False File Type 0 1 True False SELinux Type 0 2 True True * 1 0 True False model2 0 1 1 True True * 1 2 True False MLS 0 3 True True * 1 3 True True 5 0 True True 1 button5 button6 Disabled Permissive Enforcing False SELinux Administration 800 500 system-config-selinux.png True False vertical True False True False _File True True False _Add True False True image13 False _Properties True False True image14 False _Delete True False True image15 False gtk-quit True False True True True False _Help True True False gtk-about True False True True False True 0 True True True False 5 0 none True False 12 True True Select Management Object False True False <b>Select:</b> True True False True False False True False vertical True False 5 5 True False System Default Enforcing Mode 0 0 True False True model3 0 1 0 True False Current Enforcing Mode 0 1 True False True 1 1 True False System Default Policy Type: 0 2 True False True 1 2 True True False Select if you wish to relabel then entire file system on next reboot. Relabeling can take a very long time, depending on the size of the system. If you are changing policy types or going from disabled to enforcing, a relabel is required. False True True False True 0 0 True False True 2 True False gtk-refresh False False 0 True False Relabel on next reboot. True False False 1 0 3 2 True True end 0 True False vertical True False both True False Revert boolean setting to system default gtk-revert-to-saved False True True False Toggle between Customized and All Booleans Customized True gtk-find False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 10 1 True True always always True True Boolean True True 2 1 True False vertical True False both True False Add File Context gtk-add False True True False Modify File Context gtk-properties False True True False Delete File Context gtk-delete False True True False Toggle between all and customized file context Customized True gtk-find False True False False 0 True False True False Filter False False 10 0 True True True True 1 False False 1 True True always always True True File Labeling True True 2 2 True False vertical True False both True False Add SELinux User Mapping gtk-add False True True False Modify SELinux User Mapping gtk-properties False True True False Delete SELinux User Mapping gtk-delete False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 5 1 True True always always True True User Mapping True True 2 3 True False vertical True False both True False Add User gtk-add False True True False Modify User gtk-properties False True True False Delete User gtk-delete False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 5 1 True True always always True True SELinux User True True 2 4 True False vertical True False both True False Add Network Port gtk-add False True True False Edit Network Port gtk-properties False True True False Delete Network Port gtk-delete False True True False 32 True False vertical False False True False Toggle between Customized and All Ports Group View True gtk-indent False True True False Toggle between Customized and All Ports Customized True gtk-find False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 5 1 True True always always True True Network Port True True 2 5 True False vertical True False both True False Generate new policy module gtk-new False True True False Load policy module gtk-add False True True False Remove loadable policy module gtk-remove False True True False 10 True False vertical False False True False Enable/Disable additional audit rules, that are normally not reported in the log files. Enable Audit True gtk-zoom-in False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 5 1 True True always always True True Policy Module True True 2 6 True False vertical True False both True False Change process mode to permissive. Permissive True gtk-dialog-warning False True True False Change process mode to enforcing Enforcing True gtk-dialog-error False True False False 0 True False True False Filter False False 10 0 True True True True 1 False True 5 1 True True always always True True Process Domain True True 2 7 True True True True 1 False Add SELinux User dialog True False True False end gtk-cancel True True True False True True True 0 gtk-ok True True True False True True True 1 False True end 0 True False vertical True False 4 6 True False SELinux User 0 0 True False MLS/MCS Range 0 1 True True * 1 1 True False SELinux Roles 0 2 True True * 1 2 True True * 1 0 True True 5 0 True True 1 button7 button8 gui/usersPage.py0100644 0000000 0000000 00000012357 13756670063 012726 0ustar000000000 0000000 ## usersPage.py - show selinux mappings ## Copyright (C) 2006,2007,2008 Red Hat, Inc. ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program 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 General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Author: Dan Walsh import sys try: from subprocess import getstatusoutput except ImportError: from commands import getstatusoutput from gi.repository import GObject, Gtk import seobject from semanagePage import * ## ## I18N ## PROGNAME = "policycoreutils" try: import gettext kwargs = {} if sys.version_info < (3,): kwargs['unicode'] = True gettext.install(PROGNAME, localedir="/usr/share/locale", codeset='utf-8', **kwargs) except: try: import builtins builtins.__dict__['_'] = str except ImportError: import __builtin__ __builtin__.__dict__['_'] = unicode class usersPage(semanagePage): def __init__(self, xml): semanagePage.__init__(self, xml, "users", _("SELinux User")) self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.view.set_model(self.store) self.store.set_sort_column_id(0, Gtk.SortType.ASCENDING) col = Gtk.TreeViewColumn(_("SELinux\nUser"), Gtk.CellRendererText(), text=0) col.set_sort_column_id(0) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("MLS/\nMCS Range"), Gtk.CellRendererText(), text=1) col.set_resizable(True) self.view.append_column(col) col = Gtk.TreeViewColumn(_("SELinux Roles"), Gtk.CellRendererText(), text=2) col.set_resizable(True) self.view.append_column(col) self.load() self.selinuxUserEntry = xml.get_object("selinuxUserEntry") self.mlsRangeEntry = xml.get_object("mlsRangeEntry") self.selinuxRolesEntry = xml.get_object("selinuxRolesEntry") def load(self, filter=""): self.filter = filter self.user = seobject.seluserRecords() dict = self.user.get_all() self.store.clear() for k in sorted(dict.keys()): range = seobject.translate(dict[k][2]) if not (self.match(k, filter) or self.match(dict[k][0], filter) or self.match(range, filter) or self.match(dict[k][3], filter)): continue iter = self.store.append() self.store.set_value(iter, 0, k) self.store.set_value(iter, 1, range) self.store.set_value(iter, 2, dict[k][3]) self.view.get_selection().select_path((0,)) def dialogInit(self): store, iter = self.view.get_selection().get_selected() self.selinuxUserEntry.set_text(store.get_value(iter, 0)) self.selinuxUserEntry.set_sensitive(False) self.mlsRangeEntry.set_text(store.get_value(iter, 1)) self.selinuxRolesEntry.set_text(store.get_value(iter, 2)) def dialogClear(self): self.selinuxUserEntry.set_text("") self.selinuxUserEntry.set_sensitive(True) self.mlsRangeEntry.set_text("s0") self.selinuxRolesEntry.set_text("") def add(self): user = self.selinuxUserEntry.get_text() range = self.mlsRangeEntry.get_text() roles = self.selinuxRolesEntry.get_text() self.wait() (rc, out) = getstatusoutput("semanage user -a -R '%s' -r %s %s" % (roles, range, user)) self.ready() if rc != 0: self.error(out) return False iter = self.store.append() self.store.set_value(iter, 0, user) self.store.set_value(iter, 1, range) self.store.set_value(iter, 2, roles) def modify(self): user = self.selinuxUserEntry.get_text() range = self.mlsRangeEntry.get_text() roles = self.selinuxRolesEntry.get_text() self.wait() (rc, out) = getstatusoutput("semanage user -m -R '%s' -r %s %s" % (roles, range, user)) self.ready() if rc != 0: self.error(out) return False self.load(self.filter) def delete(self): store, iter = self.view.get_selection().get_selected() try: user = store.get_value(iter, 0) if user == "root" or user == "user_u": raise ValueError(_("SELinux user '%s' is required") % user) self.wait() (rc, out) = getstatusoutput("semanage user -d %s" % user) self.ready() if rc != 0: self.error(out) return False store.remove(iter) self.view.get_selection().select_path((0,)) except ValueError as e: self.error(e.args[0]) libselinux/0040755 0000000 0000000 00000000000 13756670063 012003 5ustar000000000 0000000 libselinux/Android.bp0100644 0000000 0000000 00000013505 13756670063 013707 0ustar000000000 0000000 common_CFLAGS = [ // Persistently stored patterns (pcre2) are architecture dependent. // In particular paterns built on amd64 can not run on devices with armv7 // (32bit). Therefore, this feature stays off for now. "-DNO_PERSISTENTLY_STORED_PATTERNS", "-DDISABLE_SETRANS", "-DDISABLE_BOOL", "-D_GNU_SOURCE", "-DNO_MEDIA_BACKEND", "-DNO_X_BACKEND", "-DNO_DB_BACKEND", "-Wall", "-Werror", "-Wno-error=missing-noreturn", "-Wno-error=unused-function", "-Wno-error=unused-variable", ] cc_defaults { name: "libselinux_defaults", cflags: common_CFLAGS, srcs: [ "src/booleans.c", "src/callbacks.c", "src/freecon.c", "src/label_backends_android.c", "src/label.c", "src/label_support.c", "src/matchpathcon.c", "src/setrans_client.c", "src/sha1.c", ], target: { host: { cflags: [ "-DBUILD_HOST", ], }, android: { srcs: [ "src/android/android.c", "src/avc.c", "src/avc_internal.c", "src/avc_sidtab.c", "src/canonicalize_context.c", "src/checkAccess.c", "src/check_context.c", "src/compute_av.c", "src/compute_create.c", "src/compute_member.c", "src/context.c", "src/deny_unknown.c", "src/disable.c", "src/enabled.c", "src/fgetfilecon.c", "src/fsetfilecon.c", "src/getenforce.c", "src/getfilecon.c", "src/get_initial_context.c", "src/getpeercon.c", "src/init.c", "src/lgetfilecon.c", "src/load_policy.c", "src/lsetfilecon.c", "src/mapping.c", "src/policyvers.c", "src/procattr.c", "src/reject_unknown.c", "src/sestatus.c", "src/setenforce.c", "src/setfilecon.c", "src/stringrep.c", ], shared_libs: [ "libcrypto", "liblog", ], local_include_dirs: [ "src" ], // 1003 corresponds to auditd, from system/core/logd/event.logtags cflags: [ "-DAUDITD_LOG_TAG=1003", ], } }, local_include_dirs: ["include"], export_include_dirs: ["include"], } cc_library { name: "libselinux", defaults: ["libselinux_defaults"], vendor_available: true, vndk: { enabled: true, }, double_loadable: true, recovery_available: true, host_supported: true, cflags: ["-DUSE_PCRE2"], srcs: [ "src/label_file.c", "src/regex.c", ], target: { linux_glibc: { srcs: [ "src/android/android_host.c", "src/avc.c", "src/avc_internal.c", "src/avc_sidtab.c", "src/compute_av.c", "src/compute_create.c", "src/compute_member.c", "src/context.c", "src/deny_unknown.c", "src/enabled.c", "src/fgetfilecon.c", "src/getenforce.c", "src/getfilecon.c", "src/get_initial_context.c", "src/init.c", "src/lgetfilecon.c", "src/load_policy.c", "src/lsetfilecon.c", "src/mapping.c", "src/procattr.c", "src/reject_unknown.c", "src/setenforce.c", "src/setexecfilecon.c", "src/setfilecon.c", "src/stringrep.c", ], }, linux_bionic: { enabled: true, srcs: [ "src/android/android_host.c", "src/avc.c", "src/avc_internal.c", "src/avc_sidtab.c", "src/compute_av.c", "src/compute_create.c", "src/compute_member.c", "src/context.c", "src/deny_unknown.c", "src/enabled.c", "src/getenforce.c", "src/getfilecon.c", "src/get_initial_context.c", "src/init.c", "src/load_policy.c", "src/mapping.c", "src/procattr.c", "src/reject_unknown.c", "src/setexecfilecon.c", "src/stringrep.c", ], }, android: { srcs: [ "src/android/android_platform.c", ], static: { whole_static_libs: ["libpackagelistparser"], }, shared: { shared_libs: ["libpackagelistparser"], }, version_script: "exported.map", }, vendor: { exclude_srcs: [ "src/android/android_platform.c", ], srcs: [ "src/android/android_vendor.c", ], cflags: ["-DNO_FILE_BACKEND"], exclude_shared_libs: ["libpackagelistparser"], exclude_static_libs: ["libpackagelistparser"], version_script: "exported_vendor.map", }, }, static: { whole_static_libs: ["libpcre2"], }, shared: { shared_libs: ["libpcre2"], }, } cc_binary_host { name: "sefcontext_compile", defaults: ["libselinux_defaults"], cflags: ["-DUSE_PCRE2"], srcs: ["utils/sefcontext_compile.c"], static_libs: [ "libselinux", "libsepol", ], whole_static_libs: ["libpcre2"], } libselinux/LICENSE0100644 0000000 0000000 00000002012 13756670063 013000 0ustar000000000 0000000 This library (libselinux) is public domain software, i.e. not copyrighted. Warranty Exclusion ------------------ You agree that this software is a non-commercially developed program that may contain "bugs" (as that term is used in the industry) and that it may not function as intended. The software is licensed "as is". NSA makes no, and hereby expressly disclaims all, warranties, express, implied, statutory, or otherwise with respect to the software, including noninfringement and the implied warranties of merchantability and fitness for a particular purpose. Limitation of Liability ----------------------- In no event will NSA be liable for any damages, including loss of data, lost profits, cost of cover, or other special, incidental, consequential, direct or indirect damages arising from the software or the use thereof, however caused and on any theory of liability. This limitation will apply even if NSA has been advised of the possibility of such damage. You acknowledge that this is a reasonable allocation of risk. libselinux/MODULE_LICENSE_PUBLIC_DOMAIN0100644 0000000 0000000 00000000000 13756670063 016125 0ustar000000000 0000000 libselinux/Makefile0100644 0000000 0000000 00000002531 13756670063 013441 0ustar000000000 0000000 SUBDIRS = src include utils man PKG_CONFIG ?= pkg-config DISABLE_SETRANS ?= n DISABLE_RPM ?= n ANDROID_HOST ?= n ifeq ($(ANDROID_HOST),y) override DISABLE_SETRANS=y override DISABLE_BOOL=y endif ifeq ($(DISABLE_RPM),y) DISABLE_FLAGS+= -DDISABLE_RPM endif ifeq ($(DISABLE_SETRANS),y) DISABLE_FLAGS+= -DDISABLE_SETRANS endif ifeq ($(DISABLE_BOOL),y) DISABLE_FLAGS+= -DDISABLE_BOOL endif export DISABLE_SETRANS DISABLE_RPM DISABLE_FLAGS ANDROID_HOST USE_PCRE2 ?= n ifeq ($(USE_PCRE2),y) PCRE_MODULE := libpcre2-8 PCRE_CFLAGS := -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8 else PCRE_MODULE := libpcre endif PCRE_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PCRE_MODULE)) PCRE_LDLIBS := $(shell $(PKG_CONFIG) --libs $(PCRE_MODULE)) export PCRE_MODULE PCRE_CFLAGS PCRE_LDLIBS OS := $(shell uname) export OS ifeq ($(shell $(CC) -v 2>&1 | grep "clang"),) COMPILER := gcc else COMPILER := clang endif export COMPILER all install relabel clean distclean indent: @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done swigify: all $(MAKE) -C src swigify $@ pywrap: $(MAKE) -C src pywrap $@ rubywrap: $(MAKE) -C src rubywrap $@ install-pywrap: $(MAKE) -C src install-pywrap $@ install-rubywrap: $(MAKE) -C src install-rubywrap $@ clean-pywrap: $(MAKE) -C src clean-pywrap $@ clean-rubywrap: $(MAKE) -C src clean-rubywrap $@ test: libselinux/VERSION0100644 0000000 0000000 00000000004 13756670063 013042 0ustar000000000 0000000 2.9 libselinux/exported.map0100644 0000000 0000000 00000002415 13756670063 014333 0ustar000000000 0000000 { global: fgetfilecon; fgetfilecon_raw; freecon; fsetfilecon; getcon; getfilecon; getpeercon; getpidcon; is_selinux_enabled; lgetfilecon; lsetfilecon; security_compute_create; security_get_initial_context; security_getenforce; security_load_policy; security_policyvers; security_setenforce; selabel_close; selabel_lookup; selabel_lookup_best_match; selabel_open; selinux_android_file_context_handle; selinux_android_hw_service_context_handle; selinux_android_load_policy; selinux_android_load_policy_from_fd; selinux_android_prop_context_handle; selinux_android_restorecon; selinux_android_restorecon_pkgdir; selinux_android_seapp_context_init; selinux_android_service_context_handle; selinux_android_set_sehandle; selinux_android_setcon; selinux_android_setcontext; selinux_android_vendor_service_context_handle; selinux_check_access; selinux_log_callback; selinux_set_callback; selinux_status_open; selinux_status_updated; selinux_vendor_log_callback; set_selinuxmnt; setcon; setexeccon; setfilecon; setfscreatecon; setsockcreatecon; setsockcreatecon_raw; string_to_security_class; local: *; }; libselinux/exported_vendor.map0100644 0000000 0000000 00000001430 13756670063 015704 0ustar000000000 0000000 { global: fgetfilecon; fsetfilecon; freecon; getcon; getfilecon; getpeercon; getpidcon; is_selinux_enabled; lgetfilecon; lsetfilecon; selabel_close; selabel_lookup; selabel_open; selinux_android_prop_context_handle; selinux_android_restorecon; selinux_android_service_context_handle; selinux_android_hw_service_context_handle; selinux_android_vendor_service_context_handle; selinux_check_access; security_getenforce; security_setenforce; security_load_policy; security_policyvers; selinux_log_callback; selinux_set_callback; selinux_status_open; selinux_status_updated; selinux_vendor_log_callback; setcon; setexeccon; setfilecon; setfscreatecon; local: *; }; libselinux/include/0040755 0000000 0000000 00000000000 13756670063 013426 5ustar000000000 0000000 libselinux/include/Makefile0100644 0000000 0000000 00000000514 13756670063 015063 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr INCDIR = $(PREFIX)/include/selinux all: install: all test -d $(DESTDIR)$(INCDIR) || install -m 755 -d $(DESTDIR)$(INCDIR) install -m 644 $(wildcard selinux/*.h) $(DESTDIR)$(INCDIR) relabel: indent: ../../scripts/Lindent $(wildcard selinux/*.h) distclean clean: -rm -f selinux/*~ libselinux/include/selinux/0040755 0000000 0000000 00000000000 13756670063 015115 5ustar000000000 0000000 libselinux/include/selinux/android.h0100644 0000000 0000000 00000004417 13756670063 016711 0ustar000000000 0000000 #ifndef _SELINUX_ANDROID_H_ #define _SELINUX_ANDROID_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif extern struct selabel_handle* selinux_android_file_context_handle(void); extern struct selabel_handle* selinux_android_prop_context_handle(void); extern struct selabel_handle* selinux_android_service_context_handle(void); extern struct selabel_handle* selinux_android_hw_service_context_handle(void); extern struct selabel_handle* selinux_android_vendor_service_context_handle(void); extern void selinux_android_set_sehandle(const struct selabel_handle *hndl); extern int selinux_android_load_policy(void); extern int selinux_android_load_policy_from_fd(int fd, const char *description); extern int selinux_android_setcon(const char *con); extern int selinux_android_setcontext(uid_t uid, bool isSystemServer, const char *seinfo, const char *name); extern int selinux_android_setfilecon(const char *pkgdir, const char *pkgname, const char *seinfo, uid_t uid); extern int selinux_log_callback(int type, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); // API to support legacy usecase where full-treble legacy VNDK vendor needs to use this callback. extern int selinux_vendor_log_callback(int type, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); #define SELINUX_ANDROID_RESTORECON_NOCHANGE 1 #define SELINUX_ANDROID_RESTORECON_VERBOSE 2 #define SELINUX_ANDROID_RESTORECON_RECURSE 4 #define SELINUX_ANDROID_RESTORECON_FORCE 8 #define SELINUX_ANDROID_RESTORECON_DATADATA 16 #define SELINUX_ANDROID_RESTORECON_SKIPCE 32 #define SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS 64 #define SELINUX_ANDROID_RESTORECON_SKIP_SEHASH 128 extern int selinux_android_restorecon(const char *file, unsigned int flags); extern int selinux_android_restorecon_pkgdir(const char *pkgdir, const char *seinfo, uid_t uid, unsigned int flags); extern void selinux_android_seapp_context_init(void); extern int selinux_android_seapp_context_reload(void); #ifdef __cplusplus } #endif #endif libselinux/include/selinux/av_permissions.h0100644 0000000 0000000 00000177222 13756670063 020337 0ustar000000000 0000000 #warning "Please remove any #include of this header in your source code." #warning "Instead, use string_to_av_perm() to map the permission name to a value." /* This file is automatically generated. Do not edit. */ #define COMMON_FILE__IOCTL 0x00000001UL #define COMMON_FILE__READ 0x00000002UL #define COMMON_FILE__WRITE 0x00000004UL #define COMMON_FILE__CREATE 0x00000008UL #define COMMON_FILE__GETATTR 0x00000010UL #define COMMON_FILE__SETATTR 0x00000020UL #define COMMON_FILE__LOCK 0x00000040UL #define COMMON_FILE__RELABELFROM 0x00000080UL #define COMMON_FILE__RELABELTO 0x00000100UL #define COMMON_FILE__APPEND 0x00000200UL #define COMMON_FILE__UNLINK 0x00000400UL #define COMMON_FILE__LINK 0x00000800UL #define COMMON_FILE__RENAME 0x00001000UL #define COMMON_FILE__EXECUTE 0x00002000UL #define COMMON_FILE__SWAPON 0x00004000UL #define COMMON_FILE__QUOTAON 0x00008000UL #define COMMON_FILE__MOUNTON 0x00010000UL #define COMMON_SOCKET__IOCTL 0x00000001UL #define COMMON_SOCKET__READ 0x00000002UL #define COMMON_SOCKET__WRITE 0x00000004UL #define COMMON_SOCKET__CREATE 0x00000008UL #define COMMON_SOCKET__GETATTR 0x00000010UL #define COMMON_SOCKET__SETATTR 0x00000020UL #define COMMON_SOCKET__LOCK 0x00000040UL #define COMMON_SOCKET__RELABELFROM 0x00000080UL #define COMMON_SOCKET__RELABELTO 0x00000100UL #define COMMON_SOCKET__APPEND 0x00000200UL #define COMMON_SOCKET__BIND 0x00000400UL #define COMMON_SOCKET__CONNECT 0x00000800UL #define COMMON_SOCKET__LISTEN 0x00001000UL #define COMMON_SOCKET__ACCEPT 0x00002000UL #define COMMON_SOCKET__GETOPT 0x00004000UL #define COMMON_SOCKET__SETOPT 0x00008000UL #define COMMON_SOCKET__SHUTDOWN 0x00010000UL #define COMMON_SOCKET__RECVFROM 0x00020000UL #define COMMON_SOCKET__SENDTO 0x00040000UL #define COMMON_SOCKET__RECV_MSG 0x00080000UL #define COMMON_SOCKET__SEND_MSG 0x00100000UL #define COMMON_SOCKET__NAME_BIND 0x00200000UL #define COMMON_IPC__CREATE 0x00000001UL #define COMMON_IPC__DESTROY 0x00000002UL #define COMMON_IPC__GETATTR 0x00000004UL #define COMMON_IPC__SETATTR 0x00000008UL #define COMMON_IPC__READ 0x00000010UL #define COMMON_IPC__WRITE 0x00000020UL #define COMMON_IPC__ASSOCIATE 0x00000040UL #define COMMON_IPC__UNIX_READ 0x00000080UL #define COMMON_IPC__UNIX_WRITE 0x00000100UL #define COMMON_DATABASE__CREATE 0x00000001UL #define COMMON_DATABASE__DROP 0x00000002UL #define COMMON_DATABASE__GETATTR 0x00000004UL #define COMMON_DATABASE__SETATTR 0x00000008UL #define COMMON_DATABASE__RELABELFROM 0x00000010UL #define COMMON_DATABASE__RELABELTO 0x00000020UL #define FILESYSTEM__MOUNT 0x00000001UL #define FILESYSTEM__REMOUNT 0x00000002UL #define FILESYSTEM__UNMOUNT 0x00000004UL #define FILESYSTEM__GETATTR 0x00000008UL #define FILESYSTEM__RELABELFROM 0x00000010UL #define FILESYSTEM__RELABELTO 0x00000020UL #define FILESYSTEM__TRANSITION 0x00000040UL #define FILESYSTEM__ASSOCIATE 0x00000080UL #define FILESYSTEM__QUOTAMOD 0x00000100UL #define FILESYSTEM__QUOTAGET 0x00000200UL #define DIR__IOCTL 0x00000001UL #define DIR__READ 0x00000002UL #define DIR__WRITE 0x00000004UL #define DIR__CREATE 0x00000008UL #define DIR__GETATTR 0x00000010UL #define DIR__SETATTR 0x00000020UL #define DIR__LOCK 0x00000040UL #define DIR__RELABELFROM 0x00000080UL #define DIR__RELABELTO 0x00000100UL #define DIR__APPEND 0x00000200UL #define DIR__UNLINK 0x00000400UL #define DIR__LINK 0x00000800UL #define DIR__RENAME 0x00001000UL #define DIR__EXECUTE 0x00002000UL #define DIR__SWAPON 0x00004000UL #define DIR__QUOTAON 0x00008000UL #define DIR__MOUNTON 0x00010000UL #define DIR__ADD_NAME 0x00020000UL #define DIR__REMOVE_NAME 0x00040000UL #define DIR__REPARENT 0x00080000UL #define DIR__SEARCH 0x00100000UL #define DIR__RMDIR 0x00200000UL #define DIR__OPEN 0x00400000UL #define FILE__IOCTL 0x00000001UL #define FILE__READ 0x00000002UL #define FILE__WRITE 0x00000004UL #define FILE__CREATE 0x00000008UL #define FILE__GETATTR 0x00000010UL #define FILE__SETATTR 0x00000020UL #define FILE__LOCK 0x00000040UL #define FILE__RELABELFROM 0x00000080UL #define FILE__RELABELTO 0x00000100UL #define FILE__APPEND 0x00000200UL #define FILE__UNLINK 0x00000400UL #define FILE__LINK 0x00000800UL #define FILE__RENAME 0x00001000UL #define FILE__EXECUTE 0x00002000UL #define FILE__SWAPON 0x00004000UL #define FILE__QUOTAON 0x00008000UL #define FILE__MOUNTON 0x00010000UL #define FILE__EXECUTE_NO_TRANS 0x00020000UL #define FILE__ENTRYPOINT 0x00040000UL #define FILE__EXECMOD 0x00080000UL #define FILE__OPEN 0x00100000UL #define LNK_FILE__IOCTL 0x00000001UL #define LNK_FILE__READ 0x00000002UL #define LNK_FILE__WRITE 0x00000004UL #define LNK_FILE__CREATE 0x00000008UL #define LNK_FILE__GETATTR 0x00000010UL #define LNK_FILE__SETATTR 0x00000020UL #define LNK_FILE__LOCK 0x00000040UL #define LNK_FILE__RELABELFROM 0x00000080UL #define LNK_FILE__RELABELTO 0x00000100UL #define LNK_FILE__APPEND 0x00000200UL #define LNK_FILE__UNLINK 0x00000400UL #define LNK_FILE__LINK 0x00000800UL #define LNK_FILE__RENAME 0x00001000UL #define LNK_FILE__EXECUTE 0x00002000UL #define LNK_FILE__SWAPON 0x00004000UL #define LNK_FILE__QUOTAON 0x00008000UL #define LNK_FILE__MOUNTON 0x00010000UL #define CHR_FILE__IOCTL 0x00000001UL #define CHR_FILE__READ 0x00000002UL #define CHR_FILE__WRITE 0x00000004UL #define CHR_FILE__CREATE 0x00000008UL #define CHR_FILE__GETATTR 0x00000010UL #define CHR_FILE__SETATTR 0x00000020UL #define CHR_FILE__LOCK 0x00000040UL #define CHR_FILE__RELABELFROM 0x00000080UL #define CHR_FILE__RELABELTO 0x00000100UL #define CHR_FILE__APPEND 0x00000200UL #define CHR_FILE__UNLINK 0x00000400UL #define CHR_FILE__LINK 0x00000800UL #define CHR_FILE__RENAME 0x00001000UL #define CHR_FILE__EXECUTE 0x00002000UL #define CHR_FILE__SWAPON 0x00004000UL #define CHR_FILE__QUOTAON 0x00008000UL #define CHR_FILE__MOUNTON 0x00010000UL #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL #define CHR_FILE__ENTRYPOINT 0x00040000UL #define CHR_FILE__EXECMOD 0x00080000UL #define CHR_FILE__OPEN 0x00100000UL #define BLK_FILE__IOCTL 0x00000001UL #define BLK_FILE__READ 0x00000002UL #define BLK_FILE__WRITE 0x00000004UL #define BLK_FILE__CREATE 0x00000008UL #define BLK_FILE__GETATTR 0x00000010UL #define BLK_FILE__SETATTR 0x00000020UL #define BLK_FILE__LOCK 0x00000040UL #define BLK_FILE__RELABELFROM 0x00000080UL #define BLK_FILE__RELABELTO 0x00000100UL #define BLK_FILE__APPEND 0x00000200UL #define BLK_FILE__UNLINK 0x00000400UL #define BLK_FILE__LINK 0x00000800UL #define BLK_FILE__RENAME 0x00001000UL #define BLK_FILE__EXECUTE 0x00002000UL #define BLK_FILE__SWAPON 0x00004000UL #define BLK_FILE__QUOTAON 0x00008000UL #define BLK_FILE__MOUNTON 0x00010000UL #define BLK_FILE__OPEN 0x00020000UL #define SOCK_FILE__IOCTL 0x00000001UL #define SOCK_FILE__READ 0x00000002UL #define SOCK_FILE__WRITE 0x00000004UL #define SOCK_FILE__CREATE 0x00000008UL #define SOCK_FILE__GETATTR 0x00000010UL #define SOCK_FILE__SETATTR 0x00000020UL #define SOCK_FILE__LOCK 0x00000040UL #define SOCK_FILE__RELABELFROM 0x00000080UL #define SOCK_FILE__RELABELTO 0x00000100UL #define SOCK_FILE__APPEND 0x00000200UL #define SOCK_FILE__UNLINK 0x00000400UL #define SOCK_FILE__LINK 0x00000800UL #define SOCK_FILE__RENAME 0x00001000UL #define SOCK_FILE__EXECUTE 0x00002000UL #define SOCK_FILE__SWAPON 0x00004000UL #define SOCK_FILE__QUOTAON 0x00008000UL #define SOCK_FILE__MOUNTON 0x00010000UL #define FIFO_FILE__IOCTL 0x00000001UL #define FIFO_FILE__READ 0x00000002UL #define FIFO_FILE__WRITE 0x00000004UL #define FIFO_FILE__CREATE 0x00000008UL #define FIFO_FILE__GETATTR 0x00000010UL #define FIFO_FILE__SETATTR 0x00000020UL #define FIFO_FILE__LOCK 0x00000040UL #define FIFO_FILE__RELABELFROM 0x00000080UL #define FIFO_FILE__RELABELTO 0x00000100UL #define FIFO_FILE__APPEND 0x00000200UL #define FIFO_FILE__UNLINK 0x00000400UL #define FIFO_FILE__LINK 0x00000800UL #define FIFO_FILE__RENAME 0x00001000UL #define FIFO_FILE__EXECUTE 0x00002000UL #define FIFO_FILE__SWAPON 0x00004000UL #define FIFO_FILE__QUOTAON 0x00008000UL #define FIFO_FILE__MOUNTON 0x00010000UL #define FIFO_FILE__OPEN 0x00020000UL #define FD__USE 0x00000001UL #define SOCKET__IOCTL 0x00000001UL #define SOCKET__READ 0x00000002UL #define SOCKET__WRITE 0x00000004UL #define SOCKET__CREATE 0x00000008UL #define SOCKET__GETATTR 0x00000010UL #define SOCKET__SETATTR 0x00000020UL #define SOCKET__LOCK 0x00000040UL #define SOCKET__RELABELFROM 0x00000080UL #define SOCKET__RELABELTO 0x00000100UL #define SOCKET__APPEND 0x00000200UL #define SOCKET__BIND 0x00000400UL #define SOCKET__CONNECT 0x00000800UL #define SOCKET__LISTEN 0x00001000UL #define SOCKET__ACCEPT 0x00002000UL #define SOCKET__GETOPT 0x00004000UL #define SOCKET__SETOPT 0x00008000UL #define SOCKET__SHUTDOWN 0x00010000UL #define SOCKET__RECVFROM 0x00020000UL #define SOCKET__SENDTO 0x00040000UL #define SOCKET__RECV_MSG 0x00080000UL #define SOCKET__SEND_MSG 0x00100000UL #define SOCKET__NAME_BIND 0x00200000UL #define TCP_SOCKET__IOCTL 0x00000001UL #define TCP_SOCKET__READ 0x00000002UL #define TCP_SOCKET__WRITE 0x00000004UL #define TCP_SOCKET__CREATE 0x00000008UL #define TCP_SOCKET__GETATTR 0x00000010UL #define TCP_SOCKET__SETATTR 0x00000020UL #define TCP_SOCKET__LOCK 0x00000040UL #define TCP_SOCKET__RELABELFROM 0x00000080UL #define TCP_SOCKET__RELABELTO 0x00000100UL #define TCP_SOCKET__APPEND 0x00000200UL #define TCP_SOCKET__BIND 0x00000400UL #define TCP_SOCKET__CONNECT 0x00000800UL #define TCP_SOCKET__LISTEN 0x00001000UL #define TCP_SOCKET__ACCEPT 0x00002000UL #define TCP_SOCKET__GETOPT 0x00004000UL #define TCP_SOCKET__SETOPT 0x00008000UL #define TCP_SOCKET__SHUTDOWN 0x00010000UL #define TCP_SOCKET__RECVFROM 0x00020000UL #define TCP_SOCKET__SENDTO 0x00040000UL #define TCP_SOCKET__RECV_MSG 0x00080000UL #define TCP_SOCKET__SEND_MSG 0x00100000UL #define TCP_SOCKET__NAME_BIND 0x00200000UL #define TCP_SOCKET__CONNECTTO 0x00400000UL #define TCP_SOCKET__NEWCONN 0x00800000UL #define TCP_SOCKET__ACCEPTFROM 0x01000000UL #define TCP_SOCKET__NODE_BIND 0x02000000UL #define TCP_SOCKET__NAME_CONNECT 0x04000000UL #define UDP_SOCKET__IOCTL 0x00000001UL #define UDP_SOCKET__READ 0x00000002UL #define UDP_SOCKET__WRITE 0x00000004UL #define UDP_SOCKET__CREATE 0x00000008UL #define UDP_SOCKET__GETATTR 0x00000010UL #define UDP_SOCKET__SETATTR 0x00000020UL #define UDP_SOCKET__LOCK 0x00000040UL #define UDP_SOCKET__RELABELFROM 0x00000080UL #define UDP_SOCKET__RELABELTO 0x00000100UL #define UDP_SOCKET__APPEND 0x00000200UL #define UDP_SOCKET__BIND 0x00000400UL #define UDP_SOCKET__CONNECT 0x00000800UL #define UDP_SOCKET__LISTEN 0x00001000UL #define UDP_SOCKET__ACCEPT 0x00002000UL #define UDP_SOCKET__GETOPT 0x00004000UL #define UDP_SOCKET__SETOPT 0x00008000UL #define UDP_SOCKET__SHUTDOWN 0x00010000UL #define UDP_SOCKET__RECVFROM 0x00020000UL #define UDP_SOCKET__SENDTO 0x00040000UL #define UDP_SOCKET__RECV_MSG 0x00080000UL #define UDP_SOCKET__SEND_MSG 0x00100000UL #define UDP_SOCKET__NAME_BIND 0x00200000UL #define UDP_SOCKET__NODE_BIND 0x00400000UL #define RAWIP_SOCKET__IOCTL 0x00000001UL #define RAWIP_SOCKET__READ 0x00000002UL #define RAWIP_SOCKET__WRITE 0x00000004UL #define RAWIP_SOCKET__CREATE 0x00000008UL #define RAWIP_SOCKET__GETATTR 0x00000010UL #define RAWIP_SOCKET__SETATTR 0x00000020UL #define RAWIP_SOCKET__LOCK 0x00000040UL #define RAWIP_SOCKET__RELABELFROM 0x00000080UL #define RAWIP_SOCKET__RELABELTO 0x00000100UL #define RAWIP_SOCKET__APPEND 0x00000200UL #define RAWIP_SOCKET__BIND 0x00000400UL #define RAWIP_SOCKET__CONNECT 0x00000800UL #define RAWIP_SOCKET__LISTEN 0x00001000UL #define RAWIP_SOCKET__ACCEPT 0x00002000UL #define RAWIP_SOCKET__GETOPT 0x00004000UL #define RAWIP_SOCKET__SETOPT 0x00008000UL #define RAWIP_SOCKET__SHUTDOWN 0x00010000UL #define RAWIP_SOCKET__RECVFROM 0x00020000UL #define RAWIP_SOCKET__SENDTO 0x00040000UL #define RAWIP_SOCKET__RECV_MSG 0x00080000UL #define RAWIP_SOCKET__SEND_MSG 0x00100000UL #define RAWIP_SOCKET__NAME_BIND 0x00200000UL #define RAWIP_SOCKET__NODE_BIND 0x00400000UL #define NODE__TCP_RECV 0x00000001UL #define NODE__TCP_SEND 0x00000002UL #define NODE__UDP_RECV 0x00000004UL #define NODE__UDP_SEND 0x00000008UL #define NODE__RAWIP_RECV 0x00000010UL #define NODE__RAWIP_SEND 0x00000020UL #define NODE__ENFORCE_DEST 0x00000040UL #define NODE__DCCP_RECV 0x00000080UL #define NODE__DCCP_SEND 0x00000100UL #define NODE__RECVFROM 0x00000200UL #define NODE__SENDTO 0x00000400UL #define NETIF__TCP_RECV 0x00000001UL #define NETIF__TCP_SEND 0x00000002UL #define NETIF__UDP_RECV 0x00000004UL #define NETIF__UDP_SEND 0x00000008UL #define NETIF__RAWIP_RECV 0x00000010UL #define NETIF__RAWIP_SEND 0x00000020UL #define NETIF__DCCP_RECV 0x00000040UL #define NETIF__DCCP_SEND 0x00000080UL #define NETIF__INGRESS 0x00000100UL #define NETIF__EGRESS 0x00000200UL #define NETLINK_SOCKET__IOCTL 0x00000001UL #define NETLINK_SOCKET__READ 0x00000002UL #define NETLINK_SOCKET__WRITE 0x00000004UL #define NETLINK_SOCKET__CREATE 0x00000008UL #define NETLINK_SOCKET__GETATTR 0x00000010UL #define NETLINK_SOCKET__SETATTR 0x00000020UL #define NETLINK_SOCKET__LOCK 0x00000040UL #define NETLINK_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_SOCKET__RELABELTO 0x00000100UL #define NETLINK_SOCKET__APPEND 0x00000200UL #define NETLINK_SOCKET__BIND 0x00000400UL #define NETLINK_SOCKET__CONNECT 0x00000800UL #define NETLINK_SOCKET__LISTEN 0x00001000UL #define NETLINK_SOCKET__ACCEPT 0x00002000UL #define NETLINK_SOCKET__GETOPT 0x00004000UL #define NETLINK_SOCKET__SETOPT 0x00008000UL #define NETLINK_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_SOCKET__RECVFROM 0x00020000UL #define NETLINK_SOCKET__SENDTO 0x00040000UL #define NETLINK_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_SOCKET__NAME_BIND 0x00200000UL #define PACKET_SOCKET__IOCTL 0x00000001UL #define PACKET_SOCKET__READ 0x00000002UL #define PACKET_SOCKET__WRITE 0x00000004UL #define PACKET_SOCKET__CREATE 0x00000008UL #define PACKET_SOCKET__GETATTR 0x00000010UL #define PACKET_SOCKET__SETATTR 0x00000020UL #define PACKET_SOCKET__LOCK 0x00000040UL #define PACKET_SOCKET__RELABELFROM 0x00000080UL #define PACKET_SOCKET__RELABELTO 0x00000100UL #define PACKET_SOCKET__APPEND 0x00000200UL #define PACKET_SOCKET__BIND 0x00000400UL #define PACKET_SOCKET__CONNECT 0x00000800UL #define PACKET_SOCKET__LISTEN 0x00001000UL #define PACKET_SOCKET__ACCEPT 0x00002000UL #define PACKET_SOCKET__GETOPT 0x00004000UL #define PACKET_SOCKET__SETOPT 0x00008000UL #define PACKET_SOCKET__SHUTDOWN 0x00010000UL #define PACKET_SOCKET__RECVFROM 0x00020000UL #define PACKET_SOCKET__SENDTO 0x00040000UL #define PACKET_SOCKET__RECV_MSG 0x00080000UL #define PACKET_SOCKET__SEND_MSG 0x00100000UL #define PACKET_SOCKET__NAME_BIND 0x00200000UL #define KEY_SOCKET__IOCTL 0x00000001UL #define KEY_SOCKET__READ 0x00000002UL #define KEY_SOCKET__WRITE 0x00000004UL #define KEY_SOCKET__CREATE 0x00000008UL #define KEY_SOCKET__GETATTR 0x00000010UL #define KEY_SOCKET__SETATTR 0x00000020UL #define KEY_SOCKET__LOCK 0x00000040UL #define KEY_SOCKET__RELABELFROM 0x00000080UL #define KEY_SOCKET__RELABELTO 0x00000100UL #define KEY_SOCKET__APPEND 0x00000200UL #define KEY_SOCKET__BIND 0x00000400UL #define KEY_SOCKET__CONNECT 0x00000800UL #define KEY_SOCKET__LISTEN 0x00001000UL #define KEY_SOCKET__ACCEPT 0x00002000UL #define KEY_SOCKET__GETOPT 0x00004000UL #define KEY_SOCKET__SETOPT 0x00008000UL #define KEY_SOCKET__SHUTDOWN 0x00010000UL #define KEY_SOCKET__RECVFROM 0x00020000UL #define KEY_SOCKET__SENDTO 0x00040000UL #define KEY_SOCKET__RECV_MSG 0x00080000UL #define KEY_SOCKET__SEND_MSG 0x00100000UL #define KEY_SOCKET__NAME_BIND 0x00200000UL #define UNIX_STREAM_SOCKET__IOCTL 0x00000001UL #define UNIX_STREAM_SOCKET__READ 0x00000002UL #define UNIX_STREAM_SOCKET__WRITE 0x00000004UL #define UNIX_STREAM_SOCKET__CREATE 0x00000008UL #define UNIX_STREAM_SOCKET__GETATTR 0x00000010UL #define UNIX_STREAM_SOCKET__SETATTR 0x00000020UL #define UNIX_STREAM_SOCKET__LOCK 0x00000040UL #define UNIX_STREAM_SOCKET__RELABELFROM 0x00000080UL #define UNIX_STREAM_SOCKET__RELABELTO 0x00000100UL #define UNIX_STREAM_SOCKET__APPEND 0x00000200UL #define UNIX_STREAM_SOCKET__BIND 0x00000400UL #define UNIX_STREAM_SOCKET__CONNECT 0x00000800UL #define UNIX_STREAM_SOCKET__LISTEN 0x00001000UL #define UNIX_STREAM_SOCKET__ACCEPT 0x00002000UL #define UNIX_STREAM_SOCKET__GETOPT 0x00004000UL #define UNIX_STREAM_SOCKET__SETOPT 0x00008000UL #define UNIX_STREAM_SOCKET__SHUTDOWN 0x00010000UL #define UNIX_STREAM_SOCKET__RECVFROM 0x00020000UL #define UNIX_STREAM_SOCKET__SENDTO 0x00040000UL #define UNIX_STREAM_SOCKET__RECV_MSG 0x00080000UL #define UNIX_STREAM_SOCKET__SEND_MSG 0x00100000UL #define UNIX_STREAM_SOCKET__NAME_BIND 0x00200000UL #define UNIX_STREAM_SOCKET__CONNECTTO 0x00400000UL #define UNIX_STREAM_SOCKET__NEWCONN 0x00800000UL #define UNIX_STREAM_SOCKET__ACCEPTFROM 0x01000000UL #define UNIX_DGRAM_SOCKET__IOCTL 0x00000001UL #define UNIX_DGRAM_SOCKET__READ 0x00000002UL #define UNIX_DGRAM_SOCKET__WRITE 0x00000004UL #define UNIX_DGRAM_SOCKET__CREATE 0x00000008UL #define UNIX_DGRAM_SOCKET__GETATTR 0x00000010UL #define UNIX_DGRAM_SOCKET__SETATTR 0x00000020UL #define UNIX_DGRAM_SOCKET__LOCK 0x00000040UL #define UNIX_DGRAM_SOCKET__RELABELFROM 0x00000080UL #define UNIX_DGRAM_SOCKET__RELABELTO 0x00000100UL #define UNIX_DGRAM_SOCKET__APPEND 0x00000200UL #define UNIX_DGRAM_SOCKET__BIND 0x00000400UL #define UNIX_DGRAM_SOCKET__CONNECT 0x00000800UL #define UNIX_DGRAM_SOCKET__LISTEN 0x00001000UL #define UNIX_DGRAM_SOCKET__ACCEPT 0x00002000UL #define UNIX_DGRAM_SOCKET__GETOPT 0x00004000UL #define UNIX_DGRAM_SOCKET__SETOPT 0x00008000UL #define UNIX_DGRAM_SOCKET__SHUTDOWN 0x00010000UL #define UNIX_DGRAM_SOCKET__RECVFROM 0x00020000UL #define UNIX_DGRAM_SOCKET__SENDTO 0x00040000UL #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL #define PROCESS__FORK 0x00000001UL #define PROCESS__TRANSITION 0x00000002UL #define PROCESS__SIGCHLD 0x00000004UL #define PROCESS__SIGKILL 0x00000008UL #define PROCESS__SIGSTOP 0x00000010UL #define PROCESS__SIGNULL 0x00000020UL #define PROCESS__SIGNAL 0x00000040UL #define PROCESS__PTRACE 0x00000080UL #define PROCESS__GETSCHED 0x00000100UL #define PROCESS__SETSCHED 0x00000200UL #define PROCESS__GETSESSION 0x00000400UL #define PROCESS__GETPGID 0x00000800UL #define PROCESS__SETPGID 0x00001000UL #define PROCESS__GETCAP 0x00002000UL #define PROCESS__SETCAP 0x00004000UL #define PROCESS__SHARE 0x00008000UL #define PROCESS__GETATTR 0x00010000UL #define PROCESS__SETEXEC 0x00020000UL #define PROCESS__SETFSCREATE 0x00040000UL #define PROCESS__NOATSECURE 0x00080000UL #define PROCESS__SIGINH 0x00100000UL #define PROCESS__SETRLIMIT 0x00200000UL #define PROCESS__RLIMITINH 0x00400000UL #define PROCESS__DYNTRANSITION 0x00800000UL #define PROCESS__SETCURRENT 0x01000000UL #define PROCESS__EXECMEM 0x02000000UL #define PROCESS__EXECSTACK 0x04000000UL #define PROCESS__EXECHEAP 0x08000000UL #define PROCESS__SETKEYCREATE 0x10000000UL #define PROCESS__SETSOCKCREATE 0x20000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL #define IPC__GETATTR 0x00000004UL #define IPC__SETATTR 0x00000008UL #define IPC__READ 0x00000010UL #define IPC__WRITE 0x00000020UL #define IPC__ASSOCIATE 0x00000040UL #define IPC__UNIX_READ 0x00000080UL #define IPC__UNIX_WRITE 0x00000100UL #define SEM__CREATE 0x00000001UL #define SEM__DESTROY 0x00000002UL #define SEM__GETATTR 0x00000004UL #define SEM__SETATTR 0x00000008UL #define SEM__READ 0x00000010UL #define SEM__WRITE 0x00000020UL #define SEM__ASSOCIATE 0x00000040UL #define SEM__UNIX_READ 0x00000080UL #define SEM__UNIX_WRITE 0x00000100UL #define MSGQ__CREATE 0x00000001UL #define MSGQ__DESTROY 0x00000002UL #define MSGQ__GETATTR 0x00000004UL #define MSGQ__SETATTR 0x00000008UL #define MSGQ__READ 0x00000010UL #define MSGQ__WRITE 0x00000020UL #define MSGQ__ASSOCIATE 0x00000040UL #define MSGQ__UNIX_READ 0x00000080UL #define MSGQ__UNIX_WRITE 0x00000100UL #define MSGQ__ENQUEUE 0x00000200UL #define MSG__SEND 0x00000001UL #define MSG__RECEIVE 0x00000002UL #define SHM__CREATE 0x00000001UL #define SHM__DESTROY 0x00000002UL #define SHM__GETATTR 0x00000004UL #define SHM__SETATTR 0x00000008UL #define SHM__READ 0x00000010UL #define SHM__WRITE 0x00000020UL #define SHM__ASSOCIATE 0x00000040UL #define SHM__UNIX_READ 0x00000080UL #define SHM__UNIX_WRITE 0x00000100UL #define SHM__LOCK 0x00000200UL #define SECURITY__COMPUTE_AV 0x00000001UL #define SECURITY__COMPUTE_CREATE 0x00000002UL #define SECURITY__COMPUTE_MEMBER 0x00000004UL #define SECURITY__CHECK_CONTEXT 0x00000008UL #define SECURITY__LOAD_POLICY 0x00000010UL #define SECURITY__COMPUTE_RELABEL 0x00000020UL #define SECURITY__COMPUTE_USER 0x00000040UL #define SECURITY__SETENFORCE 0x00000080UL #define SECURITY__SETBOOL 0x00000100UL #define SECURITY__SETSECPARAM 0x00000200UL #define SECURITY__SETCHECKREQPROT 0x00000400UL #define SYSTEM__IPC_INFO 0x00000001UL #define SYSTEM__SYSLOG_READ 0x00000002UL #define SYSTEM__SYSLOG_MOD 0x00000004UL #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL #define CAPABILITY__CHOWN 0x00000001UL #define CAPABILITY__DAC_OVERRIDE 0x00000002UL #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL #define CAPABILITY__FOWNER 0x00000008UL #define CAPABILITY__FSETID 0x00000010UL #define CAPABILITY__KILL 0x00000020UL #define CAPABILITY__SETGID 0x00000040UL #define CAPABILITY__SETUID 0x00000080UL #define CAPABILITY__SETPCAP 0x00000100UL #define CAPABILITY__LINUX_IMMUTABLE 0x00000200UL #define CAPABILITY__NET_BIND_SERVICE 0x00000400UL #define CAPABILITY__NET_BROADCAST 0x00000800UL #define CAPABILITY__NET_ADMIN 0x00001000UL #define CAPABILITY__NET_RAW 0x00002000UL #define CAPABILITY__IPC_LOCK 0x00004000UL #define CAPABILITY__IPC_OWNER 0x00008000UL #define CAPABILITY__SYS_MODULE 0x00010000UL #define CAPABILITY__SYS_RAWIO 0x00020000UL #define CAPABILITY__SYS_CHROOT 0x00040000UL #define CAPABILITY__SYS_PTRACE 0x00080000UL #define CAPABILITY__SYS_PACCT 0x00100000UL #define CAPABILITY__SYS_ADMIN 0x00200000UL #define CAPABILITY__SYS_BOOT 0x00400000UL #define CAPABILITY__SYS_NICE 0x00800000UL #define CAPABILITY__SYS_RESOURCE 0x01000000UL #define CAPABILITY__SYS_TIME 0x02000000UL #define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL #define CAPABILITY__MKNOD 0x08000000UL #define CAPABILITY__LEASE 0x10000000UL #define CAPABILITY__AUDIT_WRITE 0x20000000UL #define CAPABILITY__AUDIT_CONTROL 0x40000000UL #define CAPABILITY__SETFCAP 0x80000000UL #define CAPABILITY2__MAC_OVERRIDE 0x00000001UL #define CAPABILITY2__MAC_ADMIN 0x00000002UL #define PASSWD__PASSWD 0x00000001UL #define PASSWD__CHFN 0x00000002UL #define PASSWD__CHSH 0x00000004UL #define PASSWD__ROOTOK 0x00000008UL #define PASSWD__CRONTAB 0x00000010UL #define X_DRAWABLE__CREATE 0x00000001UL #define X_DRAWABLE__DESTROY 0x00000002UL #define X_DRAWABLE__READ 0x00000004UL #define X_DRAWABLE__WRITE 0x00000008UL #define X_DRAWABLE__BLEND 0x00000010UL #define X_DRAWABLE__GETATTR 0x00000020UL #define X_DRAWABLE__SETATTR 0x00000040UL #define X_DRAWABLE__LIST_CHILD 0x00000080UL #define X_DRAWABLE__ADD_CHILD 0x00000100UL #define X_DRAWABLE__REMOVE_CHILD 0x00000200UL #define X_DRAWABLE__LIST_PROPERTY 0x00000400UL #define X_DRAWABLE__GET_PROPERTY 0x00000800UL #define X_DRAWABLE__SET_PROPERTY 0x00001000UL #define X_DRAWABLE__MANAGE 0x00002000UL #define X_DRAWABLE__OVERRIDE 0x00004000UL #define X_DRAWABLE__SHOW 0x00008000UL #define X_DRAWABLE__HIDE 0x00010000UL #define X_DRAWABLE__SEND 0x00020000UL #define X_DRAWABLE__RECEIVE 0x00040000UL #define X_SCREEN__GETATTR 0x00000001UL #define X_SCREEN__SETATTR 0x00000002UL #define X_SCREEN__HIDE_CURSOR 0x00000004UL #define X_SCREEN__SHOW_CURSOR 0x00000008UL #define X_SCREEN__SAVER_GETATTR 0x00000010UL #define X_SCREEN__SAVER_SETATTR 0x00000020UL #define X_SCREEN__SAVER_HIDE 0x00000040UL #define X_SCREEN__SAVER_SHOW 0x00000080UL #define X_GC__CREATE 0x00000001UL #define X_GC__DESTROY 0x00000002UL #define X_GC__GETATTR 0x00000004UL #define X_GC__SETATTR 0x00000008UL #define X_GC__USE 0x00000010UL #define X_FONT__CREATE 0x00000001UL #define X_FONT__DESTROY 0x00000002UL #define X_FONT__GETATTR 0x00000004UL #define X_FONT__ADD_GLYPH 0x00000008UL #define X_FONT__REMOVE_GLYPH 0x00000010UL #define X_FONT__USE 0x00000020UL #define X_COLORMAP__CREATE 0x00000001UL #define X_COLORMAP__DESTROY 0x00000002UL #define X_COLORMAP__READ 0x00000004UL #define X_COLORMAP__WRITE 0x00000008UL #define X_COLORMAP__GETATTR 0x00000010UL #define X_COLORMAP__ADD_COLOR 0x00000020UL #define X_COLORMAP__REMOVE_COLOR 0x00000040UL #define X_COLORMAP__INSTALL 0x00000080UL #define X_COLORMAP__UNINSTALL 0x00000100UL #define X_COLORMAP__USE 0x00000200UL #define X_PROPERTY__CREATE 0x00000001UL #define X_PROPERTY__DESTROY 0x00000002UL #define X_PROPERTY__READ 0x00000004UL #define X_PROPERTY__WRITE 0x00000008UL #define X_PROPERTY__APPEND 0x00000010UL #define X_PROPERTY__GETATTR 0x00000020UL #define X_PROPERTY__SETATTR 0x00000040UL #define X_SELECTION__READ 0x00000001UL #define X_SELECTION__WRITE 0x00000002UL #define X_SELECTION__GETATTR 0x00000004UL #define X_SELECTION__SETATTR 0x00000008UL #define X_CURSOR__CREATE 0x00000001UL #define X_CURSOR__DESTROY 0x00000002UL #define X_CURSOR__READ 0x00000004UL #define X_CURSOR__WRITE 0x00000008UL #define X_CURSOR__GETATTR 0x00000010UL #define X_CURSOR__SETATTR 0x00000020UL #define X_CURSOR__USE 0x00000040UL #define X_CLIENT__DESTROY 0x00000001UL #define X_CLIENT__GETATTR 0x00000002UL #define X_CLIENT__SETATTR 0x00000004UL #define X_CLIENT__MANAGE 0x00000008UL #define X_DEVICE__GETATTR 0x00000001UL #define X_DEVICE__SETATTR 0x00000002UL #define X_DEVICE__USE 0x00000004UL #define X_DEVICE__READ 0x00000008UL #define X_DEVICE__WRITE 0x00000010UL #define X_DEVICE__GETFOCUS 0x00000020UL #define X_DEVICE__SETFOCUS 0x00000040UL #define X_DEVICE__BELL 0x00000080UL #define X_DEVICE__FORCE_CURSOR 0x00000100UL #define X_DEVICE__FREEZE 0x00000200UL #define X_DEVICE__GRAB 0x00000400UL #define X_DEVICE__MANAGE 0x00000800UL #define X_SERVER__GETATTR 0x00000001UL #define X_SERVER__SETATTR 0x00000002UL #define X_SERVER__RECORD 0x00000004UL #define X_SERVER__DEBUG 0x00000008UL #define X_SERVER__GRAB 0x00000010UL #define X_SERVER__MANAGE 0x00000020UL #define X_EXTENSION__QUERY 0x00000001UL #define X_EXTENSION__USE 0x00000002UL #define X_RESOURCE__READ 0x00000001UL #define X_RESOURCE__WRITE 0x00000002UL #define X_EVENT__SEND 0x00000001UL #define X_EVENT__RECEIVE 0x00000002UL #define X_SYNTHETIC_EVENT__SEND 0x00000001UL #define X_SYNTHETIC_EVENT__RECEIVE 0x00000002UL #define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL #define NETLINK_ROUTE_SOCKET__READ 0x00000002UL #define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL #define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL #define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL #define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL #define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL #define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL #define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL #define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL #define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL #define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL #define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL #define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL #define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL #define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL #define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL #define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL #define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL #define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL #define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL #define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL #define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL #define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL #define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL #define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL #define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL #define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL #define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL #define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL #define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL #define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL #define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL #define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL #define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL #define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL #define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL #define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL #define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL #define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL #define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL #define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL #define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL #define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL #define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL #define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL #define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL #define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL #define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL #define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL #define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL #define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL #define NETLINK_NFLOG_SOCKET__READ 0x00000002UL #define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL #define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL #define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL #define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL #define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL #define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL #define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL #define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL #define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL #define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL #define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL #define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL #define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL #define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL #define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL #define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL #define NETLINK_XFRM_SOCKET__READ 0x00000002UL #define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL #define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL #define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL #define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL #define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL #define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL #define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL #define NETLINK_XFRM_SOCKET__BIND 0x00000400UL #define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL #define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL #define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL #define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL #define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL #define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL #define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL #define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL #define NETLINK_SELINUX_SOCKET__READ 0x00000002UL #define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL #define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL #define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL #define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL #define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL #define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL #define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL #define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL #define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL #define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL #define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL #define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL #define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL #define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL #define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL #define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL #define NETLINK_AUDIT_SOCKET__READ 0x00000002UL #define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL #define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL #define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL #define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL #define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL #define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL #define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL #define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL #define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL #define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL #define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL #define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL #define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL #define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL #define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL #define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL #define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL #define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT 0x04000000UL #define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL #define NETLINK_IP6FW_SOCKET__READ 0x00000002UL #define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL #define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL #define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL #define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL #define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL #define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL #define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL #define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL #define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL #define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL #define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL #define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL #define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL #define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL #define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL #define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL #define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL #define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL #define NETLINK_DNRT_SOCKET__READ 0x00000002UL #define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL #define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL #define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL #define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL #define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL #define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL #define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL #define NETLINK_DNRT_SOCKET__BIND 0x00000400UL #define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL #define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL #define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL #define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL #define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL #define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL #define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL #define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_DNRT_SOCKET__NAME_BIND 0x00200000UL #define DBUS__ACQUIRE_SVC 0x00000001UL #define DBUS__SEND_MSG 0x00000002UL #define NSCD__GETPWD 0x00000001UL #define NSCD__GETGRP 0x00000002UL #define NSCD__GETHOST 0x00000004UL #define NSCD__GETSTAT 0x00000008UL #define NSCD__ADMIN 0x00000010UL #define NSCD__SHMEMPWD 0x00000020UL #define NSCD__SHMEMGRP 0x00000040UL #define NSCD__SHMEMHOST 0x00000080UL #define NSCD__GETSERV 0x00000100UL #define NSCD__SHMEMSERV 0x00000200UL #define ASSOCIATION__SENDTO 0x00000001UL #define ASSOCIATION__RECVFROM 0x00000002UL #define ASSOCIATION__SETCONTEXT 0x00000004UL #define ASSOCIATION__POLMATCH 0x00000008UL #define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL #define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL #define NETLINK_KOBJECT_UEVENT_SOCKET__WRITE 0x00000004UL #define NETLINK_KOBJECT_UEVENT_SOCKET__CREATE 0x00000008UL #define NETLINK_KOBJECT_UEVENT_SOCKET__GETATTR 0x00000010UL #define NETLINK_KOBJECT_UEVENT_SOCKET__SETATTR 0x00000020UL #define NETLINK_KOBJECT_UEVENT_SOCKET__LOCK 0x00000040UL #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELFROM 0x00000080UL #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELTO 0x00000100UL #define NETLINK_KOBJECT_UEVENT_SOCKET__APPEND 0x00000200UL #define NETLINK_KOBJECT_UEVENT_SOCKET__BIND 0x00000400UL #define NETLINK_KOBJECT_UEVENT_SOCKET__CONNECT 0x00000800UL #define NETLINK_KOBJECT_UEVENT_SOCKET__LISTEN 0x00001000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__ACCEPT 0x00002000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__GETOPT 0x00004000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__SETOPT 0x00008000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__SHUTDOWN 0x00010000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__RECVFROM 0x00020000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__SENDTO 0x00040000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL #define APPLETALK_SOCKET__IOCTL 0x00000001UL #define APPLETALK_SOCKET__READ 0x00000002UL #define APPLETALK_SOCKET__WRITE 0x00000004UL #define APPLETALK_SOCKET__CREATE 0x00000008UL #define APPLETALK_SOCKET__GETATTR 0x00000010UL #define APPLETALK_SOCKET__SETATTR 0x00000020UL #define APPLETALK_SOCKET__LOCK 0x00000040UL #define APPLETALK_SOCKET__RELABELFROM 0x00000080UL #define APPLETALK_SOCKET__RELABELTO 0x00000100UL #define APPLETALK_SOCKET__APPEND 0x00000200UL #define APPLETALK_SOCKET__BIND 0x00000400UL #define APPLETALK_SOCKET__CONNECT 0x00000800UL #define APPLETALK_SOCKET__LISTEN 0x00001000UL #define APPLETALK_SOCKET__ACCEPT 0x00002000UL #define APPLETALK_SOCKET__GETOPT 0x00004000UL #define APPLETALK_SOCKET__SETOPT 0x00008000UL #define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL #define APPLETALK_SOCKET__RECVFROM 0x00020000UL #define APPLETALK_SOCKET__SENDTO 0x00040000UL #define APPLETALK_SOCKET__RECV_MSG 0x00080000UL #define APPLETALK_SOCKET__SEND_MSG 0x00100000UL #define APPLETALK_SOCKET__NAME_BIND 0x00200000UL #define PACKET__SEND 0x00000001UL #define PACKET__RECV 0x00000002UL #define PACKET__RELABELTO 0x00000004UL #define PACKET__FLOW_IN 0x00000008UL #define PACKET__FLOW_OUT 0x00000010UL #define PACKET__FORWARD_IN 0x00000020UL #define PACKET__FORWARD_OUT 0x00000040UL #define KEY__VIEW 0x00000001UL #define KEY__READ 0x00000002UL #define KEY__WRITE 0x00000004UL #define KEY__SEARCH 0x00000008UL #define KEY__LINK 0x00000010UL #define KEY__SETATTR 0x00000020UL #define KEY__CREATE 0x00000040UL #define CONTEXT__TRANSLATE 0x00000001UL #define CONTEXT__CONTAINS 0x00000002UL #define DCCP_SOCKET__IOCTL 0x00000001UL #define DCCP_SOCKET__READ 0x00000002UL #define DCCP_SOCKET__WRITE 0x00000004UL #define DCCP_SOCKET__CREATE 0x00000008UL #define DCCP_SOCKET__GETATTR 0x00000010UL #define DCCP_SOCKET__SETATTR 0x00000020UL #define DCCP_SOCKET__LOCK 0x00000040UL #define DCCP_SOCKET__RELABELFROM 0x00000080UL #define DCCP_SOCKET__RELABELTO 0x00000100UL #define DCCP_SOCKET__APPEND 0x00000200UL #define DCCP_SOCKET__BIND 0x00000400UL #define DCCP_SOCKET__CONNECT 0x00000800UL #define DCCP_SOCKET__LISTEN 0x00001000UL #define DCCP_SOCKET__ACCEPT 0x00002000UL #define DCCP_SOCKET__GETOPT 0x00004000UL #define DCCP_SOCKET__SETOPT 0x00008000UL #define DCCP_SOCKET__SHUTDOWN 0x00010000UL #define DCCP_SOCKET__RECVFROM 0x00020000UL #define DCCP_SOCKET__SENDTO 0x00040000UL #define DCCP_SOCKET__RECV_MSG 0x00080000UL #define DCCP_SOCKET__SEND_MSG 0x00100000UL #define DCCP_SOCKET__NAME_BIND 0x00200000UL #define DCCP_SOCKET__NODE_BIND 0x00400000UL #define DCCP_SOCKET__NAME_CONNECT 0x00800000UL #define MEMPROTECT__MMAP_ZERO 0x00000001UL #define DB_DATABASE__CREATE 0x00000001UL #define DB_DATABASE__DROP 0x00000002UL #define DB_DATABASE__GETATTR 0x00000004UL #define DB_DATABASE__SETATTR 0x00000008UL #define DB_DATABASE__RELABELFROM 0x00000010UL #define DB_DATABASE__RELABELTO 0x00000020UL #define DB_DATABASE__ACCESS 0x00000040UL #define DB_DATABASE__INSTALL_MODULE 0x00000080UL #define DB_DATABASE__LOAD_MODULE 0x00000100UL #define DB_DATABASE__GET_PARAM 0x00000200UL #define DB_DATABASE__SET_PARAM 0x00000400UL #define DB_TABLE__CREATE 0x00000001UL #define DB_TABLE__DROP 0x00000002UL #define DB_TABLE__GETATTR 0x00000004UL #define DB_TABLE__SETATTR 0x00000008UL #define DB_TABLE__RELABELFROM 0x00000010UL #define DB_TABLE__RELABELTO 0x00000020UL #define DB_TABLE__USE 0x00000040UL #define DB_TABLE__SELECT 0x00000080UL #define DB_TABLE__UPDATE 0x00000100UL #define DB_TABLE__INSERT 0x00000200UL #define DB_TABLE__DELETE 0x00000400UL #define DB_TABLE__LOCK 0x00000800UL #define DB_PROCEDURE__CREATE 0x00000001UL #define DB_PROCEDURE__DROP 0x00000002UL #define DB_PROCEDURE__GETATTR 0x00000004UL #define DB_PROCEDURE__SETATTR 0x00000008UL #define DB_PROCEDURE__RELABELFROM 0x00000010UL #define DB_PROCEDURE__RELABELTO 0x00000020UL #define DB_PROCEDURE__EXECUTE 0x00000040UL #define DB_PROCEDURE__ENTRYPOINT 0x00000080UL #define DB_COLUMN__CREATE 0x00000001UL #define DB_COLUMN__DROP 0x00000002UL #define DB_COLUMN__GETATTR 0x00000004UL #define DB_COLUMN__SETATTR 0x00000008UL #define DB_COLUMN__RELABELFROM 0x00000010UL #define DB_COLUMN__RELABELTO 0x00000020UL #define DB_COLUMN__USE 0x00000040UL #define DB_COLUMN__SELECT 0x00000080UL #define DB_COLUMN__UPDATE 0x00000100UL #define DB_COLUMN__INSERT 0x00000200UL #define DB_TUPLE__RELABELFROM 0x00000001UL #define DB_TUPLE__RELABELTO 0x00000002UL #define DB_TUPLE__USE 0x00000004UL #define DB_TUPLE__SELECT 0x00000008UL #define DB_TUPLE__UPDATE 0x00000010UL #define DB_TUPLE__INSERT 0x00000020UL #define DB_TUPLE__DELETE 0x00000040UL #define DB_BLOB__CREATE 0x00000001UL #define DB_BLOB__DROP 0x00000002UL #define DB_BLOB__GETATTR 0x00000004UL #define DB_BLOB__SETATTR 0x00000008UL #define DB_BLOB__RELABELFROM 0x00000010UL #define DB_BLOB__RELABELTO 0x00000020UL #define DB_BLOB__READ 0x00000040UL #define DB_BLOB__WRITE 0x00000080UL #define DB_BLOB__IMPORT 0x00000100UL #define DB_BLOB__EXPORT 0x00000200UL #define PEER__RECV 0x00000001UL #define X_APPLICATION_DATA__PASTE 0x00000001UL #define X_APPLICATION_DATA__PASTE_AFTER_CONFIRM 0x00000002UL #define X_APPLICATION_DATA__COPY 0x00000004UL libselinux/include/selinux/avc.h0100644 0000000 0000000 00000040076 13756670063 016043 0ustar000000000 0000000 /* * Access vector cache interface for object managers. * * Author : Eamon Walsh */ #ifndef _SELINUX_AVC_H_ #define _SELINUX_AVC_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * SID format and operations */ struct security_id { char * ctx; unsigned int refcnt; }; typedef struct security_id *security_id_t; #define SECSID_WILD (security_id_t)NULL /* unspecified SID */ /** * avc_sid_to_context - get copy of context corresponding to SID. * @sid: input SID * @ctx: pointer to context reference * * Return a copy of the security context corresponding to the input * @sid in the memory referenced by @ctx. The caller is expected to * free the context with freecon(). Return %0 on success, -%1 on * failure, with @errno set to %ENOMEM if insufficient memory was * available to make the copy, or %EINVAL if the input SID is invalid. */ int avc_sid_to_context(security_id_t sid, char ** ctx); int avc_sid_to_context_raw(security_id_t sid, char ** ctx); /** * avc_context_to_sid - get SID for context. * @ctx: input security context * @sid: pointer to SID reference * * Look up security context @ctx in SID table, making * a new entry if @ctx is not found. Increment the * reference counter for the SID. Store a pointer * to the SID structure into the memory referenced by @sid, * returning %0 on success or -%1 on error with @errno set. */ int avc_context_to_sid(const char * ctx, security_id_t * sid); int avc_context_to_sid_raw(const char * ctx, security_id_t * sid); /** * sidget - increment SID reference counter. * @sid: SID reference * * Increment the reference counter for @sid, indicating that * @sid is in use by an (additional) object. Return the * new reference count, or zero if @sid is invalid (has zero * reference count). Note that avc_context_to_sid() also * increments reference counts. */ int sidget(security_id_t sid); /** * sidput - decrement SID reference counter. * @sid: SID reference * * Decrement the reference counter for @sid, indicating that * a reference to @sid is no longer in use. Return the * new reference count. When the reference count reaches * zero, the SID is invalid, and avc_context_to_sid() must * be called to obtain a new SID for the security context. */ int sidput(security_id_t sid); /** * avc_get_initial_sid - get SID for an initial kernel security identifier * @name: input name of initial kernel security identifier * @sid: pointer to a SID reference * * Get the context for an initial kernel security identifier specified by * @name using security_get_initial_context() and then call * avc_context_to_sid() to get the corresponding SID. */ int avc_get_initial_sid(const char *name, security_id_t * sid); /* * AVC entry */ struct avc_entry; struct avc_entry_ref { struct avc_entry *ae; }; /** * avc_entry_ref_init - initialize an AVC entry reference. * @aeref: pointer to avc entry reference structure * * Use this macro to initialize an avc entry reference structure * before first use. These structures are passed to avc_has_perm(), * which stores cache entry references in them. They can increase * performance on repeated queries. */ #define avc_entry_ref_init(aeref) ((aeref)->ae = NULL) /* * User-provided callbacks for memory, auditing, and locking */ /* These structures are passed by reference to avc_init(). Passing * a NULL reference will cause the AVC to use a default. The default * memory callbacks are malloc() and free(). The default logging method * is to print on stderr. If no thread callbacks are passed, a separate * listening thread won't be started for kernel policy change messages. * If no locking callbacks are passed, no locking will take place. */ struct avc_memory_callback { /* malloc() equivalent. */ void *(*func_malloc) (size_t size); /* free() equivalent. */ void (*func_free) (void *ptr); /* Note that these functions should set errno on failure. If not, some avc routines may return -1 without errno set. */ }; struct avc_log_callback { /* log the printf-style format and arguments. */ void #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) #endif (*func_log) (const char *fmt, ...); /* store a string representation of auditdata (corresponding to the given security class) into msgbuf. */ void (*func_audit) (void *auditdata, security_class_t cls, char *msgbuf, size_t msgbufsize); }; struct avc_thread_callback { /* create and start a thread, returning an opaque pointer to it; the thread should run the given function. */ void *(*func_create_thread) (void (*run) (void)); /* cancel a given thread and free its resources. */ void (*func_stop_thread) (void *thread); }; struct avc_lock_callback { /* create a lock and return an opaque pointer to it. */ void *(*func_alloc_lock) (void); /* obtain a given lock, blocking if necessary. */ void (*func_get_lock) (void *lock); /* release a given lock. */ void (*func_release_lock) (void *lock); /* destroy a given lock (free memory, etc.) */ void (*func_free_lock) (void *lock); }; /* * Available options */ /* no-op option, useful for unused slots in an array of options */ #define AVC_OPT_UNUSED 0 /* override kernel enforcing mode (boolean value) */ #define AVC_OPT_SETENFORCE 1 /* * AVC operations */ /** * avc_init - Initialize the AVC. * @msgprefix: prefix for log messages * @mem_callbacks: user-supplied memory callbacks * @log_callbacks: user-supplied logging callbacks * @thread_callbacks: user-supplied threading callbacks * @lock_callbacks: user-supplied locking callbacks * * Initialize the access vector cache. Return %0 on * success or -%1 with @errno set on failure. * If @msgprefix is NULL, use "uavc". If any callback * structure references are NULL, use default methods * for those callbacks (see the definition of the callback * structures above). */ int avc_init(const char *msgprefix, const struct avc_memory_callback *mem_callbacks, const struct avc_log_callback *log_callbacks, const struct avc_thread_callback *thread_callbacks, const struct avc_lock_callback *lock_callbacks); /** * avc_open - Initialize the AVC. * @opts: array of selabel_opt structures specifying AVC options or NULL. * @nopts: number of elements in opts array or zero for no options. * * This function is identical to avc_init(), except the message prefix * is set to "avc" and any callbacks desired should be specified via * selinux_set_callback(). Available options are listed above. */ int avc_open(struct selinux_opt *opts, unsigned nopts); /** * avc_cleanup - Remove unused SIDs and AVC entries. * * Search the SID table for SID structures with zero * reference counts, and remove them along with all * AVC entries that reference them. This can be used * to return memory to the system. */ void avc_cleanup(void); /** * avc_reset - Flush the cache and reset statistics. * * Remove all entries from the cache and reset all access * statistics (as returned by avc_cache_stats()) to zero. * The SID mapping is not affected. Return %0 on success, * -%1 with @errno set on error. */ int avc_reset(void); /** * avc_destroy - Free all AVC structures. * * Destroy all AVC structures and free all allocated * memory. User-supplied locking, memory, and audit * callbacks will be retained, but security-event * callbacks will not. All SID's will be invalidated. * User must call avc_init() if further use of AVC is desired. */ void avc_destroy(void); /** * avc_has_perm_noaudit - Check permissions but perform no auditing. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @aeref: AVC entry reference * @avd: access vector decisions * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions * based on @tclass, and call the security server on a cache miss to obtain * a new decision and add it to the cache. Update @aeref to refer to an AVC * entry with the resulting decisions, and return a copy of the decisions * in @avd. Return %0 if all @requested permissions are granted, -%1 with * @errno set to %EACCES if any permissions are denied, or to another value * upon other errors. This function is typically called by avc_has_perm(), * but may also be called directly to separate permission checking from * auditing, e.g. in cases where a lock must be held for the check but * should be released for the auditing. */ int avc_has_perm_noaudit(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct avc_entry_ref *aeref, struct av_decision *avd); /** * avc_has_perm - Check permissions and perform any appropriate auditing. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @aeref: AVC entry reference * @auditdata: auxiliary audit data * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions * based on @tclass, and call the security server on a cache miss to obtain * a new decision and add it to the cache. Update @aeref to refer to an AVC * entry with the resulting decisions. Audit the granting or denial of * permissions in accordance with the policy. Return %0 if all @requested * permissions are granted, -%1 with @errno set to %EACCES if any permissions * are denied or to another value upon other errors. */ int avc_has_perm(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct avc_entry_ref *aeref, void *auditdata); /** * avc_audit - Audit the granting or denial of permissions. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions * @avd: access vector decisions * @result: result from avc_has_perm_noaudit * @auditdata: auxiliary audit data * * Audit the granting or denial of permissions in accordance * with the policy. This function is typically called by * avc_has_perm() after a permission check, but can also be * called directly by callers who use avc_has_perm_noaudit() * in order to separate the permission check from the auditing. * For example, this separation is useful when the permission check must * be performed under a lock, to allow the lock to be released * before calling the auditing code. */ void avc_audit(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct av_decision *avd, int result, void *auditdata); /** * avc_compute_create - Compute SID for labeling a new object. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @newsid: pointer to SID reference * * Call the security server to obtain a context for labeling a * new object. Look up the context in the SID table, making * a new entry if not found. Increment the reference counter * for the SID. Store a pointer to the SID structure into the * memory referenced by @newsid, returning %0 on success or -%1 on * error with @errno set. */ int avc_compute_create(security_id_t ssid, security_id_t tsid, security_class_t tclass, security_id_t * newsid); /** * avc_compute_member - Compute SID for polyinstantation. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @newsid: pointer to SID reference * * Call the security server to obtain a context for labeling an * object instance. Look up the context in the SID table, making * a new entry if not found. Increment the reference counter * for the SID. Store a pointer to the SID structure into the * memory referenced by @newsid, returning %0 on success or -%1 on * error with @errno set. */ int avc_compute_member(security_id_t ssid, security_id_t tsid, security_class_t tclass, security_id_t * newsid); /* * security event callback facility */ /* security events */ #define AVC_CALLBACK_GRANT 1 #define AVC_CALLBACK_TRY_REVOKE 2 #define AVC_CALLBACK_REVOKE 4 #define AVC_CALLBACK_RESET 8 #define AVC_CALLBACK_AUDITALLOW_ENABLE 16 #define AVC_CALLBACK_AUDITALLOW_DISABLE 32 #define AVC_CALLBACK_AUDITDENY_ENABLE 64 #define AVC_CALLBACK_AUDITDENY_DISABLE 128 /** * avc_add_callback - Register a callback for security events. * @callback: callback function * @events: bitwise OR of desired security events * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions * * Register a callback function for events in the set @events * related to the SID pair (@ssid, @tsid) and * and the permissions @perms, interpreting * @perms based on @tclass. Returns %0 on success or * -%1 if insufficient memory exists to add the callback. */ int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, access_vector_t * out_retained), uint32_t events, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms); /* * AVC statistics */ /* If set, cache statistics are tracked. This may * become a compile-time option in the future. */ #define AVC_CACHE_STATS 1 struct avc_cache_stats { unsigned entry_lookups; unsigned entry_hits; unsigned entry_misses; unsigned entry_discards; unsigned cav_lookups; unsigned cav_hits; unsigned cav_probes; unsigned cav_misses; }; /** * avc_cache_stats - get cache access statistics. * @stats: reference to statistics structure * * Fill the supplied structure with information about AVC * activity since the last call to avc_init() or * avc_reset(). See the structure definition for * details. */ void avc_cache_stats(struct avc_cache_stats *stats); /** * avc_av_stats - log av table statistics. * * Log a message with information about the size and * distribution of the access vector table. The audit * callback is used to print the message. */ void avc_av_stats(void); /** * avc_sid_stats - log SID table statistics. * * Log a message with information about the size and * distribution of the SID table. The audit callback * is used to print the message. */ void avc_sid_stats(void); /** * avc_netlink_open - Create a netlink socket and connect to the kernel. */ int avc_netlink_open(int blocking); /** * avc_netlink_loop - Wait for netlink messages from the kernel */ void avc_netlink_loop(void); /** * avc_netlink_close - Close the netlink socket */ void avc_netlink_close(void); /** * avc_netlink_acquire_fd - Acquire netlink socket fd. * * Allows the application to manage messages from the netlink socket in * its own main loop. */ int avc_netlink_acquire_fd(void); /** * avc_netlink_release_fd - Release netlink socket fd. * * Returns ownership of the netlink socket to the library. */ void avc_netlink_release_fd(void); /** * avc_netlink_check_nb - Check netlink socket for new messages. * * Called by the application when using avc_netlink_acquire_fd() to * process kernel netlink events. */ int avc_netlink_check_nb(void); /** * selinux_status_open - Open and map SELinux kernel status page * */ int selinux_status_open(int fallback); /** * selinux_status_close - Unmap and close SELinux kernel status page * */ void selinux_status_close(void); /** * selinux_status_updated - Inform us whether the kernel status has been updated * */ int selinux_status_updated(void); /** * selinux_status_getenforce - Get the enforce flag value * */ int selinux_status_getenforce(void); /** * selinux_status_policyload - Get the number of policy reloaded * */ int selinux_status_policyload(void); /** * selinux_status_deny_unknown - Get the behavior for undefined classes/permissions * */ int selinux_status_deny_unknown(void); #ifdef __cplusplus } #endif #endif /* _SELINUX_AVC_H_ */ libselinux/include/selinux/context.h0100644 0000000 0000000 00000002271 13756670063 016751 0ustar000000000 0000000 #ifndef _SELINUX_CONTEXT_H_ #define _SELINUX_CONTEXT_H_ #ifdef __cplusplus extern "C" { #endif /* * Functions to deal with security contexts in user space. */ typedef struct { void *ptr; } context_s_t; typedef context_s_t *context_t; /* Return a new context initialized to a context string */ extern context_t context_new(const char *); /* * Return a pointer to the string value of the context_t * Valid until the next call to context_str or context_free * for the same context_t* */ extern char *context_str(context_t); /* Free the storage used by a context */ extern void context_free(context_t); /* Get a pointer to the string value of a context component */ extern const char *context_type_get(context_t); extern const char *context_range_get(context_t); extern const char *context_role_get(context_t); extern const char *context_user_get(context_t); /* Set a context component. Returns nonzero if unsuccessful */ extern int context_type_set(context_t, const char *); extern int context_range_set(context_t, const char *); extern int context_role_set(context_t, const char *); extern int context_user_set(context_t, const char *); #ifdef __cplusplus } #endif #endif libselinux/include/selinux/flask.h0100644 0000000 0000000 00000014400 13756670063 016362 0ustar000000000 0000000 /* This file is automatically generated. Do not edit. */ #ifndef _SELINUX_FLASK_H_ #define _SELINUX_FLASK_H_ #warning "Please remove any #include's of this header in your source code." #warning "Instead, use string_to_security_class() to map the class name to a value." /* * Security object class definitions */ #define SECCLASS_SECURITY 1 #define SECCLASS_PROCESS 2 #define SECCLASS_SYSTEM 3 #define SECCLASS_CAPABILITY 4 #define SECCLASS_FILESYSTEM 5 #define SECCLASS_FILE 6 #define SECCLASS_DIR 7 #define SECCLASS_FD 8 #define SECCLASS_LNK_FILE 9 #define SECCLASS_CHR_FILE 10 #define SECCLASS_BLK_FILE 11 #define SECCLASS_SOCK_FILE 12 #define SECCLASS_FIFO_FILE 13 #define SECCLASS_SOCKET 14 #define SECCLASS_TCP_SOCKET 15 #define SECCLASS_UDP_SOCKET 16 #define SECCLASS_RAWIP_SOCKET 17 #define SECCLASS_NODE 18 #define SECCLASS_NETIF 19 #define SECCLASS_NETLINK_SOCKET 20 #define SECCLASS_PACKET_SOCKET 21 #define SECCLASS_KEY_SOCKET 22 #define SECCLASS_UNIX_STREAM_SOCKET 23 #define SECCLASS_UNIX_DGRAM_SOCKET 24 #define SECCLASS_SEM 25 #define SECCLASS_MSG 26 #define SECCLASS_MSGQ 27 #define SECCLASS_SHM 28 #define SECCLASS_IPC 29 #define SECCLASS_PASSWD 30 #define SECCLASS_X_DRAWABLE 31 #define SECCLASS_X_SCREEN 32 #define SECCLASS_X_GC 33 #define SECCLASS_X_FONT 34 #define SECCLASS_X_COLORMAP 35 #define SECCLASS_X_PROPERTY 36 #define SECCLASS_X_SELECTION 37 #define SECCLASS_X_CURSOR 38 #define SECCLASS_X_CLIENT 39 #define SECCLASS_X_DEVICE 40 #define SECCLASS_X_SERVER 41 #define SECCLASS_X_EXTENSION 42 #define SECCLASS_NETLINK_ROUTE_SOCKET 43 #define SECCLASS_NETLINK_FIREWALL_SOCKET 44 #define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 #define SECCLASS_NETLINK_NFLOG_SOCKET 46 #define SECCLASS_NETLINK_XFRM_SOCKET 47 #define SECCLASS_NETLINK_SELINUX_SOCKET 48 #define SECCLASS_NETLINK_AUDIT_SOCKET 49 #define SECCLASS_NETLINK_IP6FW_SOCKET 50 #define SECCLASS_NETLINK_DNRT_SOCKET 51 #define SECCLASS_DBUS 52 #define SECCLASS_NSCD 53 #define SECCLASS_ASSOCIATION 54 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 #define SECCLASS_APPLETALK_SOCKET 56 #define SECCLASS_PACKET 57 #define SECCLASS_KEY 58 #define SECCLASS_CONTEXT 59 #define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_MEMPROTECT 61 #define SECCLASS_DB_DATABASE 62 #define SECCLASS_DB_TABLE 63 #define SECCLASS_DB_PROCEDURE 64 #define SECCLASS_DB_COLUMN 65 #define SECCLASS_DB_TUPLE 66 #define SECCLASS_DB_BLOB 67 #define SECCLASS_PEER 68 #define SECCLASS_CAPABILITY2 69 #define SECCLASS_X_RESOURCE 70 #define SECCLASS_X_EVENT 71 #define SECCLASS_X_SYNTHETIC_EVENT 72 #define SECCLASS_X_APPLICATION_DATA 73 /* * Security identifier indices for initial entities */ #define SECINITSID_KERNEL 1 #define SECINITSID_SECURITY 2 #define SECINITSID_UNLABELED 3 #define SECINITSID_FS 4 #define SECINITSID_FILE 5 #define SECINITSID_FILE_LABELS 6 #define SECINITSID_INIT 7 #define SECINITSID_ANY_SOCKET 8 #define SECINITSID_PORT 9 #define SECINITSID_NETIF 10 #define SECINITSID_NETMSG 11 #define SECINITSID_NODE 12 #define SECINITSID_IGMP_PACKET 13 #define SECINITSID_ICMP_SOCKET 14 #define SECINITSID_TCP_SOCKET 15 #define SECINITSID_SYSCTL_MODPROBE 16 #define SECINITSID_SYSCTL 17 #define SECINITSID_SYSCTL_FS 18 #define SECINITSID_SYSCTL_KERNEL 19 #define SECINITSID_SYSCTL_NET 20 #define SECINITSID_SYSCTL_NET_UNIX 21 #define SECINITSID_SYSCTL_VM 22 #define SECINITSID_SYSCTL_DEV 23 #define SECINITSID_KMOD 24 #define SECINITSID_POLICY 25 #define SECINITSID_SCMP_PACKET 26 #define SECINITSID_DEVNULL 27 #define SECINITSID_NUM 27 #endif libselinux/include/selinux/get_context_list.h0100644 0000000 0000000 00000005550 13756670063 020646 0ustar000000000 0000000 #ifndef _SELINUX_GET_SID_LIST_H_ #define _SELINUX_GET_SID_LIST_H_ #include #ifdef __cplusplus extern "C" { #endif #define SELINUX_DEFAULTUSER "user_u" /* Get an ordered list of authorized security contexts for a user session for 'user' spawned by 'fromcon' and set *conary to refer to the NULL-terminated array of contexts. Every entry in the list will be authorized by the policy, but the ordering is subject to user customizable preferences. Returns number of entries in *conary. If 'fromcon' is NULL, defaults to current context. Caller must free via freeconary. */ extern int get_ordered_context_list(const char *user, char * fromcon, char *** list); /* As above, but use the provided MLS level rather than the default level for the user. */ int get_ordered_context_list_with_level(const char *user, const char *level, char * fromcon, char *** list); /* Get the default security context for a user session for 'user' spawned by 'fromcon' and set *newcon to refer to it. The context will be one of those authorized by the policy, but the selection of a default is subject to user customizable preferences. If 'fromcon' is NULL, defaults to current context. Returns 0 on success or -1 otherwise. Caller must free via freecon. */ extern int get_default_context(const char *user, char * fromcon, char ** newcon); /* As above, but use the provided MLS level rather than the default level for the user. */ int get_default_context_with_level(const char *user, const char *level, char * fromcon, char ** newcon); /* Same as get_default_context, but only return a context that has the specified role. If no reachable context exists for the user with that role, then return -1. */ int get_default_context_with_role(const char *user, const char *role, char * fromcon, char ** newcon); /* Same as get_default_context, but only return a context that has the specified role and level. If no reachable context exists for the user with that role, then return -1. */ int get_default_context_with_rolelevel(const char *user, const char *role, const char *level, char * fromcon, char ** newcon); /* Given a list of authorized security contexts for the user, query the user to select one and set *newcon to refer to it. Caller must free via freecon. Returns 0 on sucess or -1 otherwise. */ extern int query_user_context(char ** list, char ** newcon); /* Allow the user to manually enter a context as a fallback if a list of authorized contexts could not be obtained. Caller must free via freecon. Returns 0 on success or -1 otherwise. */ extern int manual_user_enter_context(const char *user, char ** newcon); #ifdef __cplusplus } #endif #endif libselinux/include/selinux/get_default_type.h0100644 0000000 0000000 00000001165 13756670063 020612 0ustar000000000 0000000 /* get_default_type.h - contains header information and function prototypes * for functions to get the default type for a role */ #ifndef _SELINUX_GET_DEFAULT_TYPE_H_ #define _SELINUX_GET_DEFAULT_TYPE_H_ #ifdef __cplusplus extern "C" { #endif /* Return path to default type file. */ const char *selinux_default_type_path(void); /* Get the default type (domain) for 'role' and set 'type' to refer to it. Caller must free via free(). Return 0 on success or -1 otherwise. */ int get_default_type(const char *role, char **type); #ifdef __cplusplus } #endif #endif /* ifndef _GET_DEFAULT_TYPE_H_ */ libselinux/include/selinux/label.h0100644 0000000 0000000 00000013772 13756670063 016354 0ustar000000000 0000000 /* * Labeling interface for userspace object managers and others. * * Author : Eamon Walsh */ #ifndef _SELABEL_H_ #define _SELABEL_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Opaque type used for all label handles. */ struct selabel_handle; /* * Available backends. */ /* file contexts */ #define SELABEL_CTX_FILE 0 /* media contexts */ #define SELABEL_CTX_MEDIA 1 /* x contexts */ #define SELABEL_CTX_X 2 /* db objects */ #define SELABEL_CTX_DB 3 /* Android property service contexts */ #define SELABEL_CTX_ANDROID_PROP 4 /* Android service contexts */ #define SELABEL_CTX_ANDROID_SERVICE 5 /* * Available options */ /* no-op option, useful for unused slots in an array of options */ #define SELABEL_OPT_UNUSED 0 /* validate contexts before returning them (boolean value) */ #define SELABEL_OPT_VALIDATE 1 /* don't use local customizations to backend data (boolean value) */ #define SELABEL_OPT_BASEONLY 2 /* specify an alternate path to use when loading backend data */ #define SELABEL_OPT_PATH 3 /* select a subset of the search space as an optimization (file backend) */ #define SELABEL_OPT_SUBSET 4 /* require a hash calculation on spec files */ #define SELABEL_OPT_DIGEST 5 /* total number of options */ #define SELABEL_NOPT 6 /* * Label operations */ /** * selabel_open - Create a labeling handle. * @backend: one of the constants specifying a supported labeling backend. * @opts: array of selabel_opt structures specifying label options or NULL. * @nopts: number of elements in opts array or zero for no options. * * Open a labeling backend for use. The available backend identifiers are * listed above. Options may be provided via the opts parameter; available * options are listed above. Not all options may be supported by every * backend. Return value is the created handle on success or NULL with * @errno set on failure. */ struct selabel_handle *selabel_open(unsigned int backend, const struct selinux_opt *opts, unsigned nopts); /** * selabel_close - Close a labeling handle. * @handle: specifies handle to close * * Destroy the specified handle, closing files, freeing allocated memory, * etc. The handle may not be further used after it has been closed. */ void selabel_close(struct selabel_handle *handle); /** * selabel_lookup - Perform labeling lookup operation. * @handle: specifies backend instance to query * @con: returns the appropriate context with which to label the object * @key: string input to lookup operation * @type: numeric input to the lookup operation * * Perform a labeling lookup operation. Return %0 on success, -%1 with * @errno set on failure. The key and type arguments are the inputs to the * lookup operation; appropriate values are dictated by the backend in use. * The result is returned in the memory pointed to by @con and must be freed * by the user with freecon(). */ int selabel_lookup(struct selabel_handle *handle, char **con, const char *key, int type); int selabel_lookup_raw(struct selabel_handle *handle, char **con, const char *key, int type); bool selabel_partial_match(struct selabel_handle *handle, const char *key); bool selabel_hash_all_partial_matches(struct selabel_handle *rec, const char *key, uint8_t* digest); int selabel_lookup_best_match(struct selabel_handle *rec, char **con, const char *key, const char **aliases, int type); int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con, const char *key, const char **aliases, int type); /** * selabel_digest - Retrieve the SHA1 digest and the list of specfiles used to * generate the digest. The SELABEL_OPT_DIGEST option must * be set in selabel_open() to initiate the digest generation. * @handle: specifies backend instance to query * @digest: returns a pointer to the SHA1 digest. * @digest_len: returns length of digest in bytes. * @specfiles: a list of specfiles used in the SHA1 digest generation. * The list is NULL terminated and will hold @num_specfiles entries. * @num_specfiles: number of specfiles in the list. * * Return %0 on success, -%1 with @errno set on failure. */ int selabel_digest(struct selabel_handle *rec, unsigned char **digest, size_t *digest_len, char ***specfiles, size_t *num_specfiles); enum selabel_cmp_result { SELABEL_SUBSET, SELABEL_EQUAL, SELABEL_SUPERSET, SELABEL_INCOMPARABLE }; /** * selabel_cmp - Compare two label configurations. * @h1: handle for the first label configuration * @h2: handle for the first label configuration * * Compare two label configurations. * Return %SELABEL_SUBSET if @h1 is a subset of @h2, %SELABEL_EQUAL * if @h1 is identical to @h2, %SELABEL_SUPERSET if @h1 is a superset * of @h2, and %SELABEL_INCOMPARABLE if @h1 and @h2 are incomparable. */ enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1, struct selabel_handle *h2); /** * selabel_stats - log labeling operation statistics. * @handle: specifies backend instance to query * * Log a message with information about the number of queries performed, * number of unused matching entries, or other operational statistics. * Message is backend-specific, some backends may not output a message. */ void selabel_stats(struct selabel_handle *handle); /* * Type codes used by specific backends */ /* X backend */ #define SELABEL_X_PROP 1 #define SELABEL_X_EXT 2 #define SELABEL_X_CLIENT 3 #define SELABEL_X_EVENT 4 #define SELABEL_X_SELN 5 #define SELABEL_X_POLYPROP 6 #define SELABEL_X_POLYSELN 7 /* DB backend */ #define SELABEL_DB_DATABASE 1 #define SELABEL_DB_SCHEMA 2 #define SELABEL_DB_TABLE 3 #define SELABEL_DB_COLUMN 4 #define SELABEL_DB_SEQUENCE 5 #define SELABEL_DB_VIEW 6 #define SELABEL_DB_PROCEDURE 7 #define SELABEL_DB_BLOB 8 #define SELABEL_DB_TUPLE 9 #define SELABEL_DB_LANGUAGE 10 #define SELABEL_DB_EXCEPTION 11 #define SELABEL_DB_DATATYPE 12 #ifdef __cplusplus } #endif #endif /* _SELABEL_H_ */ libselinux/include/selinux/restorecon.h0100644 0000000 0000000 00000013572 13756670063 017456 0ustar000000000 0000000 #ifndef _RESTORECON_H_ #define _RESTORECON_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** * selinux_restorecon - Relabel files. * @pathname: specifies file/directory to relabel. * @restorecon_flags: specifies the actions to be performed when relabeling. * * selinux_restorecon(3) will automatically call * selinux_restorecon_default_handle(3) and selinux_restorecon_set_sehandle(3) * first time through to set the selabel_open(3) parameters to use the * currently loaded policy file_contexts and request their computed digest. * * Should other selabel_open(3) parameters be required see * selinux_restorecon_set_sehandle(3). */ extern int selinux_restorecon(const char *pathname, unsigned int restorecon_flags); /* * restorecon_flags options */ /* * Force the checking of labels even if the stored SHA1 * digest matches the specfiles SHA1 digest. */ #define SELINUX_RESTORECON_IGNORE_DIGEST 0x0001 /* * Do not change file labels. */ #define SELINUX_RESTORECON_NOCHANGE 0x0002 /* * If set, change file label to that in spec file. * If not, only change type component to that in spec file. */ #define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x0004 /* * Recursively descend directories. */ #define SELINUX_RESTORECON_RECURSE 0x0008 /* * Log changes to selinux log. Note that if VERBOSE and * PROGRESS are set, then PROGRESS will take precedence. */ #define SELINUX_RESTORECON_VERBOSE 0x0010 /* * If SELINUX_RESTORECON_PROGRESS is true and * SELINUX_RESTORECON_MASS_RELABEL is true, then output approx % complete, * else output the number of files in 1k blocks processed to stdout. */ #define SELINUX_RESTORECON_PROGRESS 0x0020 /* * Convert passed-in pathname to canonical pathname. */ #define SELINUX_RESTORECON_REALPATH 0x0040 /* * Prevent descending into directories that have a different * device number than the pathname from which the descent began. */ #define SELINUX_RESTORECON_XDEV 0x0080 /* * Attempt to add an association between an inode and a specification. * If there is already an association for the inode and it conflicts * with the specification, then use the last matching specification. */ #define SELINUX_RESTORECON_ADD_ASSOC 0x0100 /* * Abort on errors during the file tree walk. */ #define SELINUX_RESTORECON_ABORT_ON_ERROR 0x0200 /* * Log any label changes to syslog. */ #define SELINUX_RESTORECON_SYSLOG_CHANGES 0x0400 /* * Log what spec matched each file. */ #define SELINUX_RESTORECON_LOG_MATCHES 0x0800 /* * Ignore files that do not exist. */ #define SELINUX_RESTORECON_IGNORE_NOENTRY 0x1000 /* * Do not read /proc/mounts to obtain a list of non-seclabel * mounts to be excluded from relabeling checks. */ #define SELINUX_RESTORECON_IGNORE_MOUNTS 0x2000 /* * Set if there is a mass relabel required. * See SELINUX_RESTORECON_PROGRESS flag for details. */ #define SELINUX_RESTORECON_MASS_RELABEL 0x4000 /** * selinux_restorecon_set_sehandle - Set the global fc handle. * @hndl: specifies handle to set as the global fc handle. * * Called by a process that has already called selabel_open(3) with it's * required parameters, or if selinux_restorecon_default_handle(3) has been * called to set the default selabel_open(3) parameters. */ extern void selinux_restorecon_set_sehandle(struct selabel_handle *hndl); /** * selinux_restorecon_default_handle - Sets default selabel_open(3) parameters * to use the currently loaded policy and * file_contexts, also requests the digest. * * Return value is the created handle on success or NULL with @errno set on * failure. */ extern struct selabel_handle *selinux_restorecon_default_handle(void); /** * selinux_restorecon_set_exclude_list - Add a list of directories that are * to be excluded from relabeling. * @exclude_list: containing a NULL terminated list of one or more * directories not to be relabeled. */ extern void selinux_restorecon_set_exclude_list(const char **exclude_list); /** * selinux_restorecon_set_alt_rootpath - Use alternate rootpath. * @alt_rootpath: containing the alternate rootpath to be used. * * Return %0 on success, -%1 with @errno set on failure. */ extern int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath); /** * selinux_restorecon_xattr - Read/remove RESTORECON_LAST xattr entries. * @pathname: specifies directory path to check. * @xattr_flags: specifies the actions to be performed. * @xattr_list: a linked list of struct dir_xattr structures containing * the directory, digest and result of the action on the * RESTORECON_LAST entry. * * selinux_restorecon_xattr(3) will automatically call * selinux_restorecon_default_handle(3) and selinux_restorecon_set_sehandle(3) * first time through to set the selabel_open(3) parameters to use the * currently loaded policy file_contexts and request their computed digest. * * Should other selabel_open(3) parameters be required see * selinux_restorecon_set_sehandle(3), however note that a file_contexts * computed digest is required for selinux_restorecon_xattr(). */ enum digest_result { MATCH = 0, NOMATCH, DELETED_MATCH, DELETED_NOMATCH, ERROR }; struct dir_xattr { char *directory; char *digest; /* A hex encoded string that can be printed. */ enum digest_result result; struct dir_xattr *next; }; extern int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags, struct dir_xattr ***xattr_list); /* * xattr_flags options */ /* Recursively descend directories. */ #define SELINUX_RESTORECON_XATTR_RECURSE 0x0001 /* Delete non-matching digests from each directory in pathname. */ #define SELINUX_RESTORECON_XATTR_DELETE_NONMATCH_DIGESTS 0x0002 /* Delete all digests found in pathname. */ #define SELINUX_RESTORECON_XATTR_DELETE_ALL_DIGESTS 0x0004 /* Do not read /proc/mounts. */ #define SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS 0x0008 #ifdef __cplusplus } #endif #endif libselinux/include/selinux/selinux.h0100644 0000000 0000000 00000065437 13756670063 016771 0ustar000000000 0000000 #ifndef _SELINUX_H_ #define _SELINUX_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* Return 1 if we are running on a SELinux kernel, or 0 if not or -1 if we get an error. */ extern int is_selinux_enabled(void); /* Return 1 if we are running on a SELinux MLS kernel, or 0 otherwise. */ extern int is_selinux_mls_enabled(void); /* No longer used; here for compatibility with legacy callers. */ typedef char *security_context_t; /* Free the memory allocated for a context by any of the below get* calls. */ extern void freecon(char * con); /* Free the memory allocated for a context array by security_compute_user. */ extern void freeconary(char ** con); /* Wrappers for the /proc/pid/attr API. */ /* Get current context, and set *con to refer to it. Caller must free via freecon. */ extern int getcon(char ** con); extern int getcon_raw(char ** con); /* Set the current security context to con. Note that use of this function requires that the entire application be trusted to maintain any desired separation between the old and new security contexts, unlike exec-based transitions performed via setexeccon. When possible, decompose your application and use setexeccon()+execve() instead. Note that the application may lose access to its open descriptors as a result of a setcon() unless policy allows it to use descriptors opened by the old context. */ extern int setcon(const char * con); extern int setcon_raw(const char * con); /* Get context of process identified by pid, and set *con to refer to it. Caller must free via freecon. */ extern int getpidcon(pid_t pid, char ** con); extern int getpidcon_raw(pid_t pid, char ** con); /* Get previous context (prior to last exec), and set *con to refer to it. Caller must free via freecon. */ extern int getprevcon(char ** con); extern int getprevcon_raw(char ** con); /* Get exec context, and set *con to refer to it. Sets *con to NULL if no exec context has been set, i.e. using default. If non-NULL, caller must free via freecon. */ extern int getexeccon(char ** con); extern int getexeccon_raw(char ** con); /* Set exec security context for the next execve. Call with NULL if you want to reset to the default. */ extern int setexeccon(const char * con); extern int setexeccon_raw(const char * con); /* Get fscreate context, and set *con to refer to it. Sets *con to NULL if no fs create context has been set, i.e. using default. If non-NULL, caller must free via freecon. */ extern int getfscreatecon(char ** con); extern int getfscreatecon_raw(char ** con); /* Set the fscreate security context for subsequent file creations. Call with NULL if you want to reset to the default. */ extern int setfscreatecon(const char * context); extern int setfscreatecon_raw(const char * context); /* Get keycreate context, and set *con to refer to it. Sets *con to NULL if no key create context has been set, i.e. using default. If non-NULL, caller must free via freecon. */ extern int getkeycreatecon(char ** con); extern int getkeycreatecon_raw(char ** con); /* Set the keycreate security context for subsequent key creations. Call with NULL if you want to reset to the default. */ extern int setkeycreatecon(const char * context); extern int setkeycreatecon_raw(const char * context); /* Get sockcreate context, and set *con to refer to it. Sets *con to NULL if no socket create context has been set, i.e. using default. If non-NULL, caller must free via freecon. */ extern int getsockcreatecon(char ** con); extern int getsockcreatecon_raw(char ** con); /* Set the sockcreate security context for subsequent socket creations. Call with NULL if you want to reset to the default. */ extern int setsockcreatecon(const char * context); extern int setsockcreatecon_raw(const char * context); /* Wrappers for the xattr API. */ /* Get file context, and set *con to refer to it. Caller must free via freecon. */ extern int getfilecon(const char *path, char ** con); extern int getfilecon_raw(const char *path, char ** con); extern int lgetfilecon(const char *path, char ** con); extern int lgetfilecon_raw(const char *path, char ** con); extern int fgetfilecon(int fd, char ** con); extern int fgetfilecon_raw(int fd, char ** con); /* Set file context */ extern int setfilecon(const char *path, const char * con); extern int setfilecon_raw(const char *path, const char * con); extern int lsetfilecon(const char *path, const char * con); extern int lsetfilecon_raw(const char *path, const char * con); extern int fsetfilecon(int fd, const char * con); extern int fsetfilecon_raw(int fd, const char * con); /* Wrappers for the socket API */ /* Get context of peer socket, and set *con to refer to it. Caller must free via freecon. */ extern int getpeercon(int fd, char ** con); extern int getpeercon_raw(int fd, char ** con); /* Wrappers for the selinuxfs (policy) API. */ typedef unsigned int access_vector_t; typedef unsigned short security_class_t; struct av_decision { access_vector_t allowed; access_vector_t decided; access_vector_t auditallow; access_vector_t auditdeny; unsigned int seqno; unsigned int flags; }; /* Definitions of av_decision.flags */ #define SELINUX_AVD_FLAGS_PERMISSIVE 0x0001 /* Structure for passing options, used by AVC and label subsystems */ struct selinux_opt { int type; const char *value; }; /* Callback facilities */ union selinux_callback { /* log the printf-style format and arguments, with the type code indicating the type of message */ int #ifdef __GNUC__ __attribute__ ((format(printf, 2, 3))) #endif (*func_log) (int type, const char *fmt, ...); /* store a string representation of auditdata (corresponding to the given security class) into msgbuf. */ int (*func_audit) (void *auditdata, security_class_t cls, char *msgbuf, size_t msgbufsize); /* validate the supplied context, modifying if necessary */ int (*func_validate) (char **ctx); /* netlink callback for setenforce message */ int (*func_setenforce) (int enforcing); /* netlink callback for policyload message */ int (*func_policyload) (int seqno); }; #define SELINUX_CB_LOG 0 #define SELINUX_CB_AUDIT 1 #define SELINUX_CB_VALIDATE 2 #define SELINUX_CB_SETENFORCE 3 #define SELINUX_CB_POLICYLOAD 4 extern union selinux_callback selinux_get_callback(int type); extern void selinux_set_callback(int type, union selinux_callback cb); /* Logging type codes, passed to the logging callback */ #define SELINUX_ERROR 0 #define SELINUX_WARNING 1 #define SELINUX_INFO 2 #define SELINUX_AVC 3 #define SELINUX_TRANS_DIR "/var/run/setrans" /* Compute an access decision. */ extern int security_compute_av(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd); extern int security_compute_av_raw(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd); extern int security_compute_av_flags(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd); extern int security_compute_av_flags_raw(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd); /* Compute a labeling decision and set *newcon to refer to it. Caller must free via freecon. */ extern int security_compute_create(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); extern int security_compute_create_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); extern int security_compute_create_name(const char * scon, const char * tcon, security_class_t tclass, const char *objname, char ** newcon); extern int security_compute_create_name_raw(const char * scon, const char * tcon, security_class_t tclass, const char *objname, char ** newcon); /* Compute a relabeling decision and set *newcon to refer to it. Caller must free via freecon. */ extern int security_compute_relabel(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); extern int security_compute_relabel_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); /* Compute a polyinstantiation member decision and set *newcon to refer to it. Caller must free via freecon. */ extern int security_compute_member(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); extern int security_compute_member_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon); /* Compute the set of reachable user contexts and set *con to refer to the NULL-terminated array of contexts. Caller must free via freeconary. */ extern int security_compute_user(const char * scon, const char *username, char *** con); extern int security_compute_user_raw(const char * scon, const char *username, char *** con); /* Load a policy configuration. */ extern int security_load_policy(void *data, size_t len); /* Get the context of an initial kernel security identifier by name. Caller must free via freecon */ extern int security_get_initial_context(const char *name, char ** con); extern int security_get_initial_context_raw(const char *name, char ** con); /* * Make a policy image and load it. * This function provides a higher level interface for loading policy * than security_load_policy, internally determining the right policy * version, locating and opening the policy file, mapping it into memory, * manipulating it as needed for current boolean settings and/or local * definitions, and then calling security_load_policy to load it. * * 'preservebools' is a boolean flag indicating whether current * policy boolean values should be preserved into the new policy (if 1) * or reset to the saved policy settings (if 0). The former case is the * default for policy reloads, while the latter case is an option for policy * reloads but is primarily for the initial policy load. */ extern int selinux_mkload_policy(int preservebools); /* * Perform the initial policy load. * This function determines the desired enforcing mode, sets the * the *enforce argument accordingly for the caller to use, sets the * SELinux kernel enforcing status to match it, and loads the policy. * It also internally handles the initial selinuxfs mount required to * perform these actions. * * The function returns 0 if everything including the policy load succeeds. * In this case, init is expected to re-exec itself in order to transition * to the proper security context. * Otherwise, the function returns -1, and init must check *enforce to * determine how to proceed. If enforcing (*enforce > 0), then init should * halt the system. Otherwise, init may proceed normally without a re-exec. */ extern int selinux_init_load_policy(int *enforce); /* Translate boolean strict to name value pair. */ typedef struct { char *name; int value; } SELboolean; /* save a list of booleans in a single transaction. */ extern int security_set_boolean_list(size_t boolcnt, SELboolean * boollist, int permanent); /* Load policy boolean settings. Path may be NULL, in which case the booleans are loaded from the active policy boolean configuration file. */ extern int security_load_booleans(char *path); /* Check the validity of a security context. */ extern int security_check_context(const char * con); extern int security_check_context_raw(const char * con); /* Canonicalize a security context. */ extern int security_canonicalize_context(const char * con, char ** canoncon); extern int security_canonicalize_context_raw(const char * con, char ** canoncon); /* Get the enforce flag value. */ extern int security_getenforce(void); /* Set the enforce flag value. */ extern int security_setenforce(int value); /* Get the load-time behavior for undefined classes/permissions */ extern int security_reject_unknown(void); /* Get the runtime behavior for undefined classes/permissions */ extern int security_deny_unknown(void); /* Get the checkreqprot value */ extern int security_get_checkreqprot(void); /* Disable SELinux at runtime (must be done prior to initial policy load). */ extern int security_disable(void); /* Get the policy version number. */ extern int security_policyvers(void); /* Get the boolean names */ extern int security_get_boolean_names(char ***names, int *len); /* Get the pending value for the boolean */ extern int security_get_boolean_pending(const char *name); /* Get the active value for the boolean */ extern int security_get_boolean_active(const char *name); /* Set the pending value for the boolean */ extern int security_set_boolean(const char *name, int value); /* Commit the pending values for the booleans */ extern int security_commit_booleans(void); /* Userspace class mapping support */ struct security_class_mapping { const char *name; const char *perms[sizeof(access_vector_t) * 8 + 1]; }; /** * selinux_set_mapping - Enable dynamic mapping between integer offsets and security class names * @map: array of security_class_mapping structures * * The core avc_has_perm() API uses integers to represent security * classes; previous to the introduction of this function, it was * common for userspace object managers to be compiled using generated * offsets for a particular policy. However, that strongly ties the build of the userspace components to a particular policy. * * By using this function to map between integer offsets and security * class names, it's possible to replace a system policies that have * at least the same set of security class names as used by the * userspace object managers. * * To correctly use this function, you should override the generated * security class defines from the system policy in a local header, * starting at 1, and have one security_class_mapping structure entry * per define. */ extern int selinux_set_mapping(struct security_class_mapping *map); /* Common helpers */ /* Convert between mode and security class values */ extern security_class_t mode_to_security_class(mode_t mode); /* Convert between security class values and string names */ extern security_class_t string_to_security_class(const char *name); extern const char *security_class_to_string(security_class_t cls); /* Convert between individual access vector permissions and string names */ extern const char *security_av_perm_to_string(security_class_t tclass, access_vector_t perm); extern access_vector_t string_to_av_perm(security_class_t tclass, const char *name); /* Returns an access vector in a string representation. User must free the * returned string via free(). */ extern int security_av_string(security_class_t tclass, access_vector_t av, char **result); /* Display an access vector in a string representation. */ extern void print_access_vector(security_class_t tclass, access_vector_t av); /* Set the function used by matchpathcon_init when displaying errors about the file_contexts configuration. If not set, then this defaults to fprintf(stderr, fmt, ...). */ extern void set_matchpathcon_printf(void (*f) (const char *fmt, ...)); /* Set the function used by matchpathcon_init when checking the validity of a context in the file contexts configuration. If not set, then this defaults to a test based on security_check_context(). The function is also responsible for reporting any such error, and may include the 'path' and 'lineno' in such error messages. */ extern void set_matchpathcon_invalidcon(int (*f) (const char *path, unsigned lineno, char *context)); /* Same as above, but also allows canonicalization of the context, by changing *context to refer to the canonical form. If not set, and invalidcon is also not set, then this defaults to calling security_canonicalize_context(). */ extern void set_matchpathcon_canoncon(int (*f) (const char *path, unsigned lineno, char **context)); /* Set flags controlling operation of matchpathcon_init or matchpathcon. */ #define MATCHPATHCON_BASEONLY 1 /* Only process the base file_contexts file. */ #define MATCHPATHCON_NOTRANS 2 /* Do not perform any context translation. */ #define MATCHPATHCON_VALIDATE 4 /* Validate/canonicalize contexts at init time. */ extern void set_matchpathcon_flags(unsigned int flags); /* Load the file contexts configuration specified by 'path' into memory for use by subsequent matchpathcon calls. If 'path' is NULL, then load the active file contexts configuration, i.e. the path returned by selinux_file_context_path(). Unless the MATCHPATHCON_BASEONLY flag has been set, this function also checks for a 'path'.homedirs file and a 'path'.local file and loads additional specifications from them if present. */ extern int matchpathcon_init(const char *path); /* Same as matchpathcon_init, but only load entries with regexes that have stems that are prefixes of 'prefix'. */ extern int matchpathcon_init_prefix(const char *path, const char *prefix); /* Free the memory allocated by matchpathcon_init. */ extern void matchpathcon_fini(void); /* Resolve all of the symlinks and relative portions of a pathname, but NOT * the final component (same a realpath() unless the final component is a * symlink. Resolved path must be a path of size PATH_MAX + 1 */ extern int realpath_not_final(const char *name, char *resolved_path); /* Match the specified pathname and mode against the file contexts configuration and set *con to refer to the resulting context. 'mode' can be 0 to disable mode matching. Caller must free via freecon. If matchpathcon_init has not already been called, then this function will call it upon its first invocation with a NULL path. */ extern int matchpathcon(const char *path, mode_t mode, char ** con); /* Same as above, but return a specification index for later use in a matchpathcon_filespec_add() call - see below. */ extern int matchpathcon_index(const char *path, mode_t mode, char ** con); /* Maintain an association between an inode and a specification index, and check whether a conflicting specification is already associated with the same inode (e.g. due to multiple hard links). If so, then use the latter of the two specifications based on their order in the file contexts configuration. Return the used specification index. */ extern int matchpathcon_filespec_add(ino_t ino, int specind, const char *file); /* Destroy any inode associations that have been added, e.g. to restart for a new filesystem. */ extern void matchpathcon_filespec_destroy(void); /* Display statistics on the hash table usage for the associations. */ extern void matchpathcon_filespec_eval(void); /* Check to see whether any specifications had no matches and report them. The 'str' is used as a prefix for any warning messages. */ extern void matchpathcon_checkmatches(char *str); /* Match the specified media and against the media contexts configuration and set *con to refer to the resulting context. Caller must free con via freecon. */ extern int matchmediacon(const char *media, char ** con); /* selinux_getenforcemode reads the /etc/selinux/config file and determines whether the machine should be started in enforcing (1), permissive (0) or disabled (-1) mode. */ extern int selinux_getenforcemode(int *enforce); /* selinux_boolean_sub reads the /etc/selinux/TYPE/booleans.subs_dist file looking for a record with boolean_name. If a record exists selinux_boolean_sub returns the translated name otherwise it returns the original name. The returned value needs to be freed. On failure NULL will be returned. */ extern char *selinux_boolean_sub(const char *boolean_name); /* selinux_getpolicytype reads the /etc/selinux/config file and determines what the default policy for the machine is. Calling application must free policytype. */ extern int selinux_getpolicytype(char **policytype); /* selinux_policy_root reads the /etc/selinux/config file and returns the directory path under which the compiled policy file and context configuration files exist. */ extern const char *selinux_policy_root(void); /* selinux_set_policy_root sets an alternate policy root directory path under which the compiled policy file and context configuration files exist. */ extern int selinux_set_policy_root(const char *rootpath); /* These functions return the paths to specific files under the policy root directory. */ extern const char *selinux_current_policy_path(void); extern const char *selinux_binary_policy_path(void); extern const char *selinux_failsafe_context_path(void); extern const char *selinux_removable_context_path(void); extern const char *selinux_default_context_path(void); extern const char *selinux_user_contexts_path(void); extern const char *selinux_file_context_path(void); extern const char *selinux_file_context_homedir_path(void); extern const char *selinux_file_context_local_path(void); extern const char *selinux_file_context_subs_path(void); extern const char *selinux_file_context_subs_dist_path(void); extern const char *selinux_homedir_context_path(void); extern const char *selinux_media_context_path(void); extern const char *selinux_virtual_domain_context_path(void); extern const char *selinux_virtual_image_context_path(void); extern const char *selinux_lxc_contexts_path(void); extern const char *selinux_x_context_path(void); extern const char *selinux_sepgsql_context_path(void); extern const char *selinux_openrc_contexts_path(void); extern const char *selinux_openssh_contexts_path(void); extern const char *selinux_snapperd_contexts_path(void); extern const char *selinux_systemd_contexts_path(void); extern const char *selinux_contexts_path(void); extern const char *selinux_securetty_types_path(void); extern const char *selinux_booleans_subs_path(void); extern const char *selinux_booleans_path(void); extern const char *selinux_customizable_types_path(void); extern const char *selinux_users_path(void); extern const char *selinux_usersconf_path(void); extern const char *selinux_translations_path(void); extern const char *selinux_colors_path(void); extern const char *selinux_netfilter_context_path(void); extern const char *selinux_path(void); /** * selinux_check_access - Check permissions and perform appropriate auditing. * @scon: source security context * @tcon: target security context * @tclass: target security class string * @perm: requested permissions string, interpreted based on @tclass * @auditdata: auxiliary audit data * * Check the AVC to determine whether the @perm permissions are granted * for the SID pair (@scon, @tcon), interpreting the permissions * based on @tclass. * Return %0 if all @perm permissions are granted, -%1 with * @errno set to %EACCES if any permissions are denied or to another * value upon other errors. * If auditing or logging is configured the appropriate callbacks will be called * and passed the auditdata field */ extern int selinux_check_access(const char * scon, const char * tcon, const char *tclass, const char *perm, void *auditdata); /* Check a permission in the passwd class. Return 0 if granted or -1 otherwise. */ extern int selinux_check_passwd_access(access_vector_t requested); extern int checkPasswdAccess(access_vector_t requested); /* Check if the tty_context is defined as a securetty Return 0 if secure, < 0 otherwise. */ extern int selinux_check_securetty_context(const char * tty_context); /* Set the path to the selinuxfs mount point explicitly. Normally, this is determined automatically during libselinux initialization, but this is not always possible, e.g. for /sbin/init which performs the initial mount of selinuxfs. */ void set_selinuxmnt(const char *mnt); /* Check if selinuxfs exists as a kernel filesystem */ int selinuxfs_exists(void); /* clear selinuxmnt variable and free allocated memory */ void fini_selinuxmnt(void); /* Set an appropriate security context based on the filename of a helper * program, falling back to a new context with the specified type. */ extern int setexecfilecon(const char *filename, const char *fallback_type); #ifndef DISABLE_RPM /* Execute a helper for rpm in an appropriate security context. */ extern int rpm_execcon(unsigned int verified, const char *filename, char *const argv[], char *const envp[]); #endif /* Returns whether a file context is customizable, and should not be relabeled . */ extern int is_context_customizable(const char * scontext); /* Perform context translation between the human-readable format ("translated") and the internal system format ("raw"). Caller must free the resulting context via freecon. Returns -1 upon an error or 0 otherwise. If passed NULL, sets the returned context to NULL and returns 0. */ extern int selinux_trans_to_raw_context(const char * trans, char ** rawp); extern int selinux_raw_to_trans_context(const char * raw, char ** transp); /* Perform context translation between security contexts and display colors. Returns a space-separated list of ten ten hex RGB triples prefixed by hash marks, e.g. "#ff0000". Caller must free the resulting string via free. Returns -1 upon an error or 0 otherwise. */ extern int selinux_raw_context_to_color(const char * raw, char **color_str); /* Get the SELinux username and level to use for a given Linux username. These values may then be passed into the get_ordered_context_list* and get_default_context* functions to obtain a context for the user. Returns 0 on success or -1 otherwise. Caller must free the returned strings via free. */ extern int getseuserbyname(const char *linuxuser, char **seuser, char **level); /* Get the SELinux username and level to use for a given Linux username and service. These values may then be passed into the get_ordered_context_list* and get_default_context* functions to obtain a context for the user. Returns 0 on success or -1 otherwise. Caller must free the returned strings via free. */ extern int getseuser(const char *username, const char *service, char **r_seuser, char **r_level); /* Compare two file contexts, return 0 if equivalent. */ extern int selinux_file_context_cmp(const char * a, const char * b); /* * Verify the context of the file 'path' against policy. * Return 1 if match, 0 if not and -1 on error. */ extern int selinux_file_context_verify(const char *path, mode_t mode); /* This function sets the file context on to the system defaults returns 0 on success */ extern int selinux_lsetfilecon_default(const char *path); /* * Force a reset of the loaded configuration * WARNING: This is not thread safe. Be very sure that no other threads * are calling into libselinux when this is called. */ extern void selinux_reset_config(void); #ifdef __cplusplus } #endif #endif libselinux/man/0040755 0000000 0000000 00000000000 13756670063 012556 5ustar000000000 0000000 libselinux/man/Makefile0100644 0000000 0000000 00000002153 13756670063 014214 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 MAN5SUBDIR ?= man5 MAN8SUBDIR ?= man8 MAN3DIR ?= $(MANDIR)/$(MAN3SUBDIR) MAN5DIR ?= $(MANDIR)/$(MAN5SUBDIR) MAN8DIR ?= $(MANDIR)/$(MAN8SUBDIR) all: install: all mkdir -p $(DESTDIR)$(MAN3DIR) mkdir -p $(DESTDIR)$(MAN5DIR) mkdir -p $(DESTDIR)$(MAN8DIR) install -m 644 man3/*.3 $(DESTDIR)$(MAN3DIR) install -m 644 man5/*.5 $(DESTDIR)$(MAN5DIR) install -m 644 man8/*.8 $(DESTDIR)$(MAN8DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man3 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ install -m 644 $${lang}/man3/*.3 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ fi ; \ if [ -e $${lang}/man5 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN5SUBDIR) ; \ install -m 644 $${lang}/man5/*.5 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN5SUBDIR) ; \ fi ; \ if [ -e $${lang}/man8 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ install -m 644 $${lang}/man8/*.8 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ fi ; \ done relabel: indent distclean clean: libselinux/man/man3/0040755 0000000 0000000 00000000000 13756670063 013414 5ustar000000000 0000000 libselinux/man/man3/avc_add_callback.30100644 0000000 0000000 00000012012 13756670063 016666 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2004 .TH "avc_add_callback" "3" "9 June 2004" "" "SELinux API documentation" .SH "NAME" avc_add_callback \- additional event notification for SELinux userspace object managers . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_add_callback(int (*" callback ")(uint32_t " event , .in +\w'int avc_add_callback(int (*callback)('u .BI "security_id_t " ssid , .br .BI "security_id_t " tsid , .br .BI "security_class_t " tclass , .br .BI "access_vector_t " perms , .br .BI "access_vector_t *" out_retained ")," .in .in +\w'int avc_add_callback('u .BI "uint32_t " events ", security_id_t " ssid , .br .BI "security_id_t " tsid ", security_class_t " tclass , .br .BI "access_vector_t " perms ");" .in . .SH "DESCRIPTION" .BR avc_add_callback () is used to register callback functions on security events. The purpose of this functionality is to allow userspace object managers to take additional action when a policy change, usually a policy reload, causes permissions to be granted or revoked. .I events is the .RI bitwise- or of security events on which to register the callback; see .B SECURITY EVENTS below. .IR ssid , .IR tsid , .IR tclass , and .I perms specify the source and target SID's, target class, and specific permissions that the callback wishes to monitor. The special symbol .B SECSID_WILD may be passed as the .I source or .I target and will cause any SID to match. .I callback is the callback function provided by the userspace object manager. The .I event argument indicates the security event which occurred; the remaining arguments are interpreted according to the event as described below. The return value of the callback should be zero on success, \-1 on error with .I errno set appropriately (but see .B RETURN VALUE below). . .SH "SECURITY EVENTS" In all cases below, .I ssid and/or .I tsid may be set to .BR SECSID_WILD , indicating that the change applies to all source and/or target SID's. Unless otherwise indicated, the .I out_retained parameter is unused. . .TP .B AVC_CALLBACK_GRANT Previously denied permissions are now granted for .IR ssid , .I tsid with respect to .IR tclass . .I perms indicates the permissions to grant. .TP .B AVC_CALLBACK_TRY_REVOKE Previously granted permissions are now conditionally revoked for .IR ssid , .I tsid with respect to .IR tclass . .I perms indicates the permissions to revoke. The callback should set .I out_retained to the subset of .I perms which are retained as migrated permissions. Note that .I out_retained is ignored if the callback returns \-1. .TP .B AVC_CALLBACK_REVOKE Previously granted permissions are now unconditionally revoked for .IR ssid , .I tsid with respect to .IR tclass . .I perms indicates the permissions to revoke. .TP .B AVC_CALLBACK_RESET Indicates that the cache was flushed. The SID, class, and permission arguments are unused and are set to NULL. .TP .B AVC_CALLBACK_AUDITALLOW_ENABLE The permissions given by .I perms should now be audited when granted for .IR ssid , .I tsid with respect to .IR tclass . .TP .B AVC_CALLBACK_AUDITALLOW_DISABLE The permissions given by .I perms should no longer be audited when granted for .IR ssid , .I tsid with respect to .IR tclass . .TP .B AVC_CALLBACK_AUDITDENY_ENABLE The permissions given by .I perms should now be audited when denied for .IR ssid , .I tsid with respect to .IR tclass . .TP .B AVC_CALLBACK_AUDITDENY_DISABLE The permissions given by .I perms should no longer be audited when denied for .IR ssid , .I tsid with respect to .IR tclass . . .SH "RETURN VALUE" On success, .BR avc_add_callback () returns zero. On error, \-1 is returned and .I errno is set appropriately. A return value of \-1 from a callback is interpreted as a failed policy operation. If such a return value is encountered, all remaining callbacks registered on the event are called. In threaded mode, the netlink handler thread may then terminate and cause the userspace AVC to return .B EINVAL on all further permission checks until .BR avc_destroy (3) is called. In non-threaded mode, the permission check on which the error occurred will return \-1 and the value of .I errno encountered to the caller. In both cases, a log message is produced and the kernel may be notified of the error. . .SH "ERRORS" .TP .B ENOMEM An attempt to allocate memory failed. . .SH "NOTES" If the userspace AVC is running in threaded mode, callbacks registered via .BR avc_add_callback () may be executed in the context of the netlink handler thread. This will likely introduce synchronization issues requiring the use of locks. See .BR avc_init (3). Support for dynamic revocation and retained permissions is mostly unimplemented in the SELinux kernel module. The only security event that currently gets exercised is .BR AVC_CALLBACK_RESET . . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .ad l .nh .BR avc_init (3), .BR avc_has_perm (3), .BR avc_context_to_sid (3), .BR avc_cache_stats (3), .BR security_compute_av (3) .BR selinux (8) libselinux/man/man3/avc_audit.30100644 0000000 0000000 00000000030 13756670063 015425 0ustar000000000 0000000 .so man3/avc_has_perm.3 libselinux/man/man3/avc_av_stats.30100644 0000000 0000000 00000000033 13756670063 016146 0ustar000000000 0000000 .so man3/avc_cache_stats.3 libselinux/man/man3/avc_cache_stats.30100644 0000000 0000000 00000004427 13756670063 016616 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2004 .TH "avc_cache_stats" "3" "27 May 2004" "" "SELinux API documentation" .SH "NAME" avc_cache_stats, avc_av_stats, avc_sid_stats \- obtain userspace SELinux AVC statistics . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "void avc_av_stats(void);" .sp .BI "void avc_sid_stats(void);" .sp .BI "void avc_cache_stats(struct avc_cache_stats *" stats ");" . .SH "DESCRIPTION" The userspace AVC maintains two internal hash tables, one to store security ID's and one to cache access decisions. .BR avc_av_stats () and .BR avc_sid_stats () produce log messages indicating the status of the access decision and SID tables, respectively. The messages contain the number of entries in the table, number of hash buckets and number of buckets used, and maximum number of entries in a single bucket. .BR avc_cache_stats () populates a structure whose fields reflect cache activity: .RS .ta 4n 14n .nf struct avc_cache_stats { unsigned entry_lookups; unsigned entry_hits; unsigned entry_misses; unsigned entry_discards; unsigned cav_lookups; unsigned cav_hits; unsigned cav_probes; unsigned cav_misses; }; .fi .ta .RE .TP .I entry_lookups Number of queries made. .TP .I entry_hits Number of times a decision was found in the .I aeref argument. .TP .I entry_misses Number of times a decision was not found in the .I aeref argument. .TP .I entry_discards Number of times a decision was not found in the .I aeref argument and the .I aeref argument was non-NULL. .TP .I cav_lookups Number of cache lookups. .TP .I cav_hits Number of cache hits. .TP .I cav_misses Number of cache misses. .TP .I cav_probes Number of entries examined while searching the cache. . .SH "NOTES" When the cache is flushed as a result of a call to .BR avc_reset () or a policy change notification, the statistics returned by .BR avc_cache_stats () are reset to zero. The SID table, however, is left unchanged. When a policy change notification is received, a call to .BR avc_av_stats () is made before the cache is flushed. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .ad l .nh .BR avc_init (3), .BR avc_has_perm (3), .BR avc_context_to_sid (3), .BR avc_add_callback (3), .BR selinux (8) libselinux/man/man3/avc_cleanup.30100644 0000000 0000000 00000000024 13756670063 015751 0ustar000000000 0000000 .so man3/avc_open.3 libselinux/man/man3/avc_compute_create.30100644 0000000 0000000 00000003510 13756670063 017324 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "avc_compute_create" "3" "30 Mar 2007" "" "SELinux API documentation" .SH "NAME" avc_compute_create, avc_compute_member \- obtain SELinux label for new object . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_compute_create(security_id_t " ssid ", security_id_t " tsid , .in +\w'int avc_compute_create('u .BI "security_class_t " tclass ", security_id_t *" newsid ");" .sp .in .BI "int avc_compute_member(security_id_t " ssid ", security_id_t " tsid , .in +\w'int avc_compute_member('u .BI "security_class_t " tclass ", security_id_t *" newsid ");" .in . .SH "DESCRIPTION" .BR avc_compute_create () is used to compute a SID to use for labeling a new object in a particular class based on a SID pair. This call is identical to .BR security_compute_create (), but does not require converting from userspace SID's to contexts and back again. .BR avc_compute_member () is used to compute a SID to use for labeling a polyinstantiated object instance of a particular class based on a SID pair. This call is identical to .BR security_compute_member (), but does not require converting from userspace SID's to contexts and back again. These functions return a SID for the computed context in the memory referenced by .IR sid . . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B EINVAL The .I tclass and/or the security contexts referenced by .I ssid and .I tsid are not recognized by the currently loaded policy. .TP .B ENOMEM An attempt to allocate memory failed. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR avc_init (3), .BR avc_context_to_sid (3), .BR security_compute_create (3), .BR selinux (8) libselinux/man/man3/avc_compute_member.30100644 0000000 0000000 00000000036 13756670063 017330 0ustar000000000 0000000 .so man3/avc_compute_create.3 libselinux/man/man3/avc_context_to_sid.30100644 0000000 0000000 00000003510 13756670063 017352 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2004 .TH "avc_context_to_sid" "3" "27 May 2004" "" "SELinux API documentation" .SH "NAME" avc_context_to_sid, avc_sid_to_context, avc_get_initial_sid \- obtain and manipulate SELinux security ID's . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_context_to_sid(char *" ctx ", security_id_t *" sid ");" .sp .BI "int avc_sid_to_context(security_id_t " sid ", char **" ctx ");" .sp .BI "int avc_get_initial_sid(const char *" name ", security_id_t *" sid ");" . .SH "DESCRIPTION" Security ID's (SID's) are opaque representations of security contexts, managed by the userspace AVC. .BR avc_context_to_sid () returns a SID for the given .I context in the memory referenced by .IR sid . .BR avc_sid_to_context () returns a copy of the context represented by .I sid in the memory referenced by .IR ctx . The user must free the copy with .BR freecon (3). .BR avc_get_initial_sid () returns a SID for the kernel initial security identifier specified by .IR name . . .SH "RETURN VALUE" .BR avc_context_to_sid () and .BR avc_sid_to_context () return zero on success. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B ENOMEM An attempt to allocate memory failed. .SH "NOTES" As of libselinux version 2.0.86, SID's are no longer reference counted. A SID will be valid from the time it is first obtained until the next call to .BR avc_destroy (3). The .BR sidget (3) and .BR sidput (3) functions, formerly used to adjust the reference count, are no-ops and are deprecated. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .ad l .nh .BR avc_init (3), .BR avc_has_perm (3), .BR avc_cache_stats (3), .BR avc_add_callback (3), .BR getcon (3), .BR freecon (3), .BR selinux (8) libselinux/man/man3/avc_destroy.30100644 0000000 0000000 00000000024 13756670063 016013 0ustar000000000 0000000 .so man3/avc_open.3 libselinux/man/man3/avc_entry_ref_init.30100644 0000000 0000000 00000000030 13756670063 017337 0ustar000000000 0000000 .so man3/avc_has_perm.3 libselinux/man/man3/avc_get_initial_context.30100644 0000000 0000000 00000000036 13756670063 020361 0ustar000000000 0000000 .so man3/avc_context_to_sid.3 libselinux/man/man3/avc_get_initial_sid.30100644 0000000 0000000 00000000036 13756670063 017454 0ustar000000000 0000000 .so man3/avc_context_to_sid.3 libselinux/man/man3/avc_has_perm.30100644 0000000 0000000 00000010222 13756670063 016121 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2004 .TH "avc_has_perm" "3" "27 May 2004" "" "SELinux API documentation" .SH "NAME" avc_has_perm, avc_has_perm_noaudit, avc_audit, avc_entry_ref_init \- obtain and audit SELinux access decisions . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "void avc_entry_ref_init(struct avc_entry_ref *" aeref ");" .sp .BI "int avc_has_perm(security_id_t " ssid ", security_id_t " tsid , .in +\w'int avc_has_perm('u .BI "security_class_t " tclass ", access_vector_t " requested , .br .BI "struct avc_entry_ref *" aeref ", void *" auditdata ");" .in .sp .BI "int avc_has_perm_noaudit(security_id_t " ssid ", security_id_t " tsid , .in +\w'int avc_has_perm('u .BI "security_class_t " tclass ", access_vector_t " requested , .br .BI "struct avc_entry_ref *" aeref ", struct av_decision *" avd ");" .in .sp .BI "void avc_audit(security_id_t " ssid ", security_id_t " tsid , .in +\w'void avc_audit('u .BI "security_class_t " tclass ", access_vector_t " requested , .br .BI "struct av_decision *" avd ", int " result ", void *" auditdata ");" .in . .SH "DESCRIPTION" .BR avc_entry_ref_init () initializes an .B avc_entry_ref structure; see .B ENTRY REFERENCES below. This function may be implemented as a macro. .BR avc_has_perm () checks whether the .I requested permissions are granted for subject SID .IR ssid and target SID .IR tsid , interpreting the permissions based on .I tclass and updating .IR aeref , if non-NULL, to refer to a cache entry with the resulting decision. The granting or denial of permissions is audited in accordance with the policy. The .I auditdata parameter is for supplemental auditing; see .BR avc_audit () below. .BR avc_has_perm_noaudit () behaves as .BR avc_has_perm () without producing an audit message. The access decision is returned in .I avd and can be passed to .BR avc_audit () explicitly. .BR avc_audit () produces an audit message for the access query represented by .IR ssid , .IR tsid , .IR tclass , and .IR requested , with a decision represented by .IR avd . Pass the value returned by .BR avc_has_perm_noaudit () as .IR result . The .I auditdata parameter is passed to the user-supplied .B func_audit callback and can be used to add supplemental information to the audit message; see .BR avc_init (3). . .SH "ENTRY REFERENCES" Entry references can be used to speed cache performance for repeated queries on the same subject and target. The userspace AVC will check the .I aeref argument, if supplied, before searching the cache on a permission query. After a query is performed, .I aeref will be updated to reference the cache entry for that query. A subsequent query on the same subject and target will then have the decision at hand without having to walk the cache. After declaring an .B avc_entry_ref structure, use .BR avc_entry_ref_init () to initialize it before passing it to .BR avc_has_perm () or .BR \%avc_has_perm_noaudit () for the first time. Using an uninitialized structure will produce undefined behavior. . .SH "RETURN VALUE" If requested permissions are granted, zero is returned. If requested permissions are denied or an error occurred, \-1 is returned and .I errno is set appropriately. In permissive mode, zero will be returned and .I errno unchanged even if permissions were denied. .BR avc_has_perm () will still produce an audit message in this case. . .SH "ERRORS" .TP .B EACCES A requested permission was denied. .TP .B EINVAL The .I tclass and/or the security contexts referenced by .I ssid and .I tsid are not recognized by the currently loaded policy. .TP .B ENOMEM An attempt to allocate memory failed. . .SH "NOTES" Internal errors encountered by the userspace AVC may cause certain values of .I errno to be returned unexpectedly. For example, netlink socket errors may produce .B EACCES or .BR EINVAL . Make sure that userspace object managers are granted appropriate access to netlink by the policy. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .ad l .nh .BR avc_init (3), .BR avc_context_to_sid (3), .BR avc_cache_stats (3), .BR avc_add_callback (3), .BR security_compute_av (3), .BR selinux (8) libselinux/man/man3/avc_has_perm_noaudit.30100644 0000000 0000000 00000000030 13756670063 017640 0ustar000000000 0000000 .so man3/avc_has_perm.3 libselinux/man/man3/avc_init.30100644 0000000 0000000 00000013107 13756670063 015273 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2004 .TH "avc_init" "3" "27 May 2004" "" "SELinux API documentation" .SH "NAME" avc_init \- legacy userspace SELinux AVC setup . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_init(const char *" msgprefix , .in +\w'int avc_init('u .BI "const struct avc_memory_callback *" mem_callbacks , .br .BI "const struct avc_log_callback *" log_callbacks , .br .BI "const struct avc_thread_callback *" thread_callbacks , .br .BI "const struct avc_lock_callback *" lock_callbacks ");" . .SH "DESCRIPTION" .BR avc_init () is deprecated; please use .BR avc_open (3) in conjunction with .BR selinux_set_callback (3) in all new code. .BR avc_init () initializes the userspace AVC and must be called before any other AVC operation can be performed. A non-NULL .I msgprefix will be prepended to all audit messages produced by the userspace AVC. The default is `uavc'. The remaining arguments, if non-NULL, specify callbacks to be used by the userspace AVC. . .SH "CALLBACKS" The userspace AVC can be directed how to perform memory allocation, logging, thread creation, and locking via callback functions passed to .BR avc_init (). The purpose of this functionality is to allow the userspace AVC to be smoothly integrated into existing userspace object managers. Use an .B avc_memory_callback structure to specify alternate functions for dynamic memory allocation. .RS .ta 4n 10n 24n .nf struct avc_memory_callback { void *(*func_malloc)(size_t size); void (*func_free)(void *ptr); }; .fi .ta .RE The two fields of the structure should be pointers to functions which behave as .BR malloc (3) and .BR free (3), which are used by default. Use an .B avc_log_callback structure to specify alternate functions for logging. .RS .ta 4n 10n 24n .nf struct avc_log_callback { void (*func_log)(const char *fmt, ...); void (*func_audit)(void *auditdata, security_class_t class, char *msgbuf, size_t msgbufsize); }; .fi .ta .RE The .B func_log callback should accept a .BR printf (3) style format and arguments and log them as desired. The default behavior prints the message on the standard error. The .B func_audit callback should interpret the .I auditdata parameter for the given .IR class , printing a human-readable interpretation to .I msgbuf using no more than .I msgbufsize characters. The default behavior is to ignore .IR auditdata . Use an .B avc_thread_callback structure to specify functions for starting and manipulating threads. .RS .ta 4n 10n 24n .nf struct avc_thread_callback { void *(*func_create_thread)(void (*run)(void)); void (*func_stop_thread)(void *thread); }; .fi .ta .RE The .B func_create_thread callback should create a new thread and return a pointer which references it. The thread should execute the .I run argument, which does not return under normal conditions. The .B func_stop_thread callback should cancel the running thread referenced by .IR thread . By default, threading is not used; see .B NETLINK NOTIFICATION below. Use an .B avc_lock_callback structure to specify functions to create, obtain, and release locks for use by threads. .RS .ta 4n 10n 24n .nf struct avc_lock_callback { void *(*func_alloc_lock)(void); void (*func_get_lock)(void *lock); void (*func_release_lock)(void *lock); void (*func_free_lock)(void *lock); }; .fi .ta .RE The .B func_alloc_lock callback should create a new lock, returning a pointer which references it. The .B func_get_lock callback should obtain .IR lock , blocking if necessary. The .B func_release_lock callback should release .IR lock . The .B func_free_lock callback should destroy .IR lock , freeing any resources associated with it. The default behavior is not to perform any locking. Note that undefined behavior may result if threading is used without appropriate locking. . .SH "NETLINK NOTIFICATION" Beginning with version 2.6.4, the Linux kernel supports SELinux status change notification via netlink. Two message types are currently implemented, indicating changes to the enforcing mode and to the loaded policy in the kernel, respectively. The userspace AVC listens for these messages and takes the appropriate action, modifying the behavior of .BR avc_has_perm (3) to reflect the current enforcing mode and flushing the cache on receipt of a policy load notification. Audit messages are produced when netlink notifications are processed. In the default single-threaded mode, the userspace AVC checks for new netlink messages at the start of each permission query. If threading and locking callbacks are passed to .BR avc_init () however, a dedicated thread will be started to listen on the netlink socket. This may increase performance and will ensure that log messages are generated immediately rather than at the time of the next permission query. . .SH "RETURN VALUE" Functions with a return value return zero on success. On error, \-1 is returned and .I errno is set appropriately. . .SH "NOTES" The .I msgprefix argument to .BR avc_init () currently has a length limit of 15 characters and will be truncated if necessary. If a provided .B func_malloc callback does not set .I errno appropriately on error, userspace AVC calls may exhibit the same behavior. If a netlink thread has been created and an error occurs on the socket (such as an access error), the thread may terminate and cause the userspace AVC to return .B EINVAL on all further permission checks until .B avc_destroy is called. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR avc_open (3), .BR selinux_set_callback (3), .BR selinux (8) libselinux/man/man3/avc_netlink_acquire_fd.30100644 0000000 0000000 00000000034 13756670063 020151 0ustar000000000 0000000 .so man3/avc_netlink_loop.3 libselinux/man/man3/avc_netlink_check_nb.30100644 0000000 0000000 00000000034 13756670063 017603 0ustar000000000 0000000 .so man3/avc_netlink_loop.3 libselinux/man/man3/avc_netlink_close.30100644 0000000 0000000 00000000034 13756670063 017154 0ustar000000000 0000000 .so man3/avc_netlink_loop.3 libselinux/man/man3/avc_netlink_loop.30100644 0000000 0000000 00000005173 13756670063 017031 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: KaiGai Kohei (kaigai@ak.jp.nec.com) 2009 .TH "avc_netlink_loop" "3" "30 Mar 2009" "" "SELinux API documentation" .SH "NAME" avc_netlink_open, avc_netlink_close, avc_netlink_acquire_fd, avc_netlink_release_fd, avc_netlink_check_nb, avc_netlink_loop \- SELinux netlink processing . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_netlink_open(int " blocking ");" .sp .B void avc_netlink_close(void); .sp .B int avc_netlink_acquire_fd(void); .sp .B void avc_netlink_release_fd(void); .sp .B void avc_netlink_loop(void); .sp .B int avc_netlink_check_nb(void); . .SH "DESCRIPTION" These functions enable applications to handle notification of SELinux events via netlink. The userspace AVC normally checks for netlink messages on each call to .BR avc_has_perm (3). Applications may wish to override this behavior and check for notification separately, for example in a .BR select (2) loop. These functions also permit netlink monitoring without requiring a call to .BR avc_open (3). .BR avc_netlink_open () opens a netlink socket to receive SELinux notifications. The socket descriptor is stored internally; use .BR avc_netlink_acquire_fd (3) to take ownership of it in application code. The .I blocking argument controls whether the O_NONBLOCK flag is set on the socket descriptor. .BR avc_open (3) calls this function internally, specifying non-blocking behavior. .BR avc_netlink_close () closes the netlink socket. This function is called automatically by .BR avc_destroy (3). .BR avc_netlink_acquire_fd () returns the netlink socket descriptor number and informs the userspace AVC not to check the socket descriptor automatically on calls to .BR avc_has_perm (3). .BR avc_netlink_release_fd () returns control of the netlink socket to the userspace AVC, re-enabling automatic processing of notifications. .BR avc_netlink_check_nb () checks the netlink socket for pending messages and processes them. Callbacks for policyload and enforcing changes will be called; see .BR selinux_set_callback (3). This function does not block. .BR avc_netlink_loop () enters a loop blocking on the netlink socket and processing messages as they are received. This function will not return unless an error occurs on the socket, in which case the socket is closed. . .SH "RETURN VALUE" .BR avc_netlink_acquire_fd () returns a non-negative file descriptor number on success. Other functions with a return value return zero on success. On error, \-1 is returned and .I errno is set appropriately. . .SH "SEE ALSO" .BR avc_open (3), .BR selinux_set_callback (3), .BR selinux (8) libselinux/man/man3/avc_netlink_open.30100644 0000000 0000000 00000000034 13756670063 017010 0ustar000000000 0000000 .so man3/avc_netlink_loop.3 libselinux/man/man3/avc_netlink_release_fd.30100644 0000000 0000000 00000000034 13756670063 020140 0ustar000000000 0000000 .so man3/avc_netlink_loop.3 libselinux/man/man3/avc_open.30100644 0000000 0000000 00000005067 13756670063 015277 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2008 .TH "avc_open" "3" "12 Jun 2008" "" "SELinux API documentation" .SH "NAME" avc_open, avc_destroy, avc_reset, avc_cleanup \- userspace SELinux AVC setup and teardown . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int avc_open(struct selinux_opt *" options ", unsigned " nopt ");" .sp .BI "void avc_destroy(void);" .sp .BI "int avc_reset(void);" .sp .BI "void avc_cleanup(void);" . .SH "DESCRIPTION" .BR avc_open () initializes the userspace AVC and must be called before any other AVC operation can be performed. .BR avc_destroy () destroys the userspace AVC, freeing all internal memory structures. After this call has been made, .BR avc_open () must be called again before any AVC operations can be performed. .BR avc_reset () flushes the userspace AVC, causing it to forget any cached access decisions. The userspace AVC normally calls this function automatically when needed, see .B NETLINK NOTIFICATION below. .BR avc_cleanup () attempts to free unused memory within the userspace AVC, but does not flush any cached access decisions. Under normal operation, calling this function should not be necessary. .SH "OPTIONS" The userspace AVC obeys callbacks set via .BR selinux_set_callback (3), in particular the logging and audit callbacks. The options which may be passed to .BR avc_open () include the following: .TP .B AVC_OPT_SETENFORCE This option forces the userspace AVC into enforcing mode if the option value is non-NULL; permissive mode otherwise. The system enforcing mode will be ignored. . .SH "NETLINK NOTIFICATION" Beginning with version 2.6.4, the Linux kernel supports SELinux status change notification via netlink. Two message types are currently implemented, indicating changes to the enforcing mode and to the loaded policy in the kernel, respectively. The userspace AVC listens for these messages and takes the appropriate action, modifying the behavior of .BR avc_has_perm (3) to reflect the current enforcing mode and flushing the cache on receipt of a policy load notification. Audit messages are produced when netlink notifications are processed. . .SH "RETURN VALUE" Functions with a return value return zero on success. On error, \-1 is returned and .I errno is set appropriately. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR selinux (8), .BR avc_has_perm (3), .BR avc_context_to_sid (3), .BR avc_cache_stats (3), .BR avc_add_callback (3), .BR selinux_set_callback (3), .BR security_compute_av (3) libselinux/man/man3/avc_reset.30100644 0000000 0000000 00000000024 13756670063 015444 0ustar000000000 0000000 .so man3/avc_open.3 libselinux/man/man3/avc_sid_stats.30100644 0000000 0000000 00000000033 13756670063 016317 0ustar000000000 0000000 .so man3/avc_cache_stats.3 libselinux/man/man3/avc_sid_to_context.30100644 0000000 0000000 00000000036 13756670063 017352 0ustar000000000 0000000 .so man3/avc_context_to_sid.3 libselinux/man/man3/checkPasswdAccess.30100644 0000000 0000000 00000000037 13756670063 017056 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/context_free.30100644 0000000 0000000 00000000027 13756670063 016161 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_new.30100644 0000000 0000000 00000004276 13756670063 016043 0ustar000000000 0000000 .TH "context_new" "3" "20 December 2011" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" context_new, context_str, context_free, context_type_get, context_type_set, context_range_get, context_range_set,context_role_get, context_role_set, context_user_get, context_user_set \- Routines to manipulate SELinux security contexts . .SH "SYNOPSIS" .B #include .sp .BI "context_t context_new(const char *" context_str ); .sp .BI "const char * context_str(context_t " con ); .sp .BI "void context_free(context_t " con ); .sp .BI "const char * context_type_get(context_t " con ); .sp .BI "const char * context_range_get(context_t " con ); .sp .BI "const char * context_role_get(context_t " con ); .sp .BI "const char * context_user_get(context_t " con ); .sp .BI "int context_type_set(context_t " con ", const char *" type ); .sp .BI "int context_range_set(context_t " con ", const char *" range ); .sp .BI "int context_role_set(context_t " con ", const char *" role ); .sp .BI "int context_user_set(context_t " con ", const char *" user ); . .SH "DESCRIPTION" These functions allow an application to manipulate the fields of a security context string without requiring it to know the format of the string. .BR context_new () returns a new context initialized to a context string. .BR context_str () returns a pointer to the string value of the .BR context_t , valid until the next call to .BR context_str () or .BR context_free () for the same .BR context_t* . .BR context_free () frees the storage used by a context. .BR context_type_get (), .BR context_range_get (), .BR context_role_get (), .BR \%context_user_get () get a pointer to the string value of a context component. .B Note: Values returned by the get functions are only valid until the next call to a set function or .BR context_free () for the same .B context_t structure. .BR context_type_set (), .BR context_range_set (), .BR context_role_set (), .BR \%context_user_set () set a context component. . .SH "RETURN VALUE" On failure .BR context_*_set () functions return non-zero and 0 on success. The other functions return NULL on failure and non-NULL on success. On failure .I errno is set appropriately. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/context_range_get.30100644 0000000 0000000 00000000027 13756670063 017173 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_range_set.30100644 0000000 0000000 00000000027 13756670063 017207 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_role_get.30100644 0000000 0000000 00000000027 13756670063 017040 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_role_set.30100644 0000000 0000000 00000000027 13756670063 017054 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_type_get.30100644 0000000 0000000 00000000027 13756670063 017060 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_type_set.30100644 0000000 0000000 00000000027 13756670063 017074 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_user_get.30100644 0000000 0000000 00000000027 13756670063 017055 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/context_user_set.30100644 0000000 0000000 00000000027 13756670063 017071 0ustar000000000 0000000 .so man3/context_new.3 libselinux/man/man3/fgetfilecon.30100644 0000000 0000000 00000000026 13756670063 015760 0ustar000000000 0000000 .so man3/getfilecon.3 libselinux/man/man3/fgetfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016631 0ustar000000000 0000000 .so man3/getfilecon.3 libselinux/man/man3/fini_selinuxmnt.30100644 0000000 0000000 00000000033 13756670063 016704 0ustar000000000 0000000 .so man3/init_selinuxmnt.3 libselinux/man/man3/freecon.30100644 0000000 0000000 00000000022 13756670063 015110 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/freeconary.30100644 0000000 0000000 00000000022 13756670063 015624 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/fsetfilecon.30100644 0000000 0000000 00000000026 13756670063 015774 0ustar000000000 0000000 .so man3/setfilecon.3 libselinux/man/man3/fsetfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016645 0ustar000000000 0000000 .so man3/setfilecon.3 libselinux/man/man3/get_default_context.30100644 0000000 0000000 00000000044 13756670063 017522 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/get_default_context_with_level.30100644 0000000 0000000 00000000044 13756670063 021744 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/get_default_context_with_role.30100644 0000000 0000000 00000000044 13756670063 021576 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/get_default_context_with_rolelevel.30100644 0000000 0000000 00000000044 13756670063 022626 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/get_default_type.30100644 0000000 0000000 00000000044 13756670063 017017 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/get_ordered_context_list.30100644 0000000 0000000 00000007234 13756670063 020565 0ustar000000000 0000000 .TH "get_ordered_context_list" "3" "1 January 2004" "russell@coker.com.au" "SELinux" .SH "NAME" get_ordered_context_list, get_ordered_context_list_with_level, get_default_context, get_default_context_with_level, get_default_context_with_role, get_default_context_with_rolelevel, query_user_context, manual_user_enter_context, get_default_role \- determine SELinux context(s) for user sessions . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int get_ordered_context_list(const char *" user ", char *" fromcon ", char ***" list ); .sp .BI "int get_ordered_context_list_with_level(const char *" user ", const char *" level ", char *" fromcon ", char ***" list ); .sp .BI "int get_default_context(const char *" user ", char *" fromcon ", char **" newcon ); .sp .BI "int get_default_context_with_level(const char *" user ", const char *" level ", char *" fromcon ", char **" newcon ); .sp .BI "int get_default_context_with_role(const char *" user ", const char *" role ", char *" fromcon ", char **" newcon "); .sp .BI "int get_default_context_with_rolelevel(const char *" user ", const char *" role ", const char *" level ", char *" fromcon ", char **" newcon "); .sp .BI "int query_user_context(char **" list ", char **" newcon ); .sp .BI "int manual_user_enter_context(const char *" user ", char **" newcon ); .sp .BI "int get_default_type(const char *" role ", char **" type ); . .SH "DESCRIPTION" .BR get_ordered_context_list () invokes the .BR security_compute_user (3) function to obtain the list of contexts for the specified .I user that are reachable from the specified .I fromcon context. The function then orders the resulting list based on the global .I \%/etc/selinux/{SELINUXTYPE}/contexts/default_contexts file and the per-user .I \%/etc/selinux/{SELINUXTYPE}/contexts/users/ file if it exists. The .I fromcon parameter may be NULL to indicate that the current context should be used. The function returns the number of contexts in the list, or \-1 upon errors. The list must be freed using the .BR freeconary (3) function. .BR get_ordered_context_list_with_level () invokes the .BR \%get_ordered_context_list () function and applies the specified level. .BR get_default_context () is the same as .BR get_ordered_context_list () but only returns a single context which has to be freed with .BR freecon (3). .BR get_default_context_with_level () invokes the .BR get_default_context () function and applies the specified level. .BR get_default_context_with_role () is the same as .BR get_default_context () but only returns a context with the specified role, returning \-1 if no such context is reachable for the user. .BR get_default_context_with_rolelevel () invokes the .BR \%get_default_context_with_role () function and applies the specified level. .BR query_user_context () takes a list of contexts, queries the user via stdin/stdout as to which context they want, and returns a new context as selected by the user (which has to be freed with .BR freecon (3)). .BR manual_user_enter_context () allows the user to manually enter a context as a fallback if a list of authorized contexts could not be obtained. Caller must free via .BR freecon (3). .BR get_default_type () Get the default type (domain) for .I role and set .I type to refer to it, which has to be freed with free. . .SH "RETURN VALUE" .BR get_ordered_context_list () and .BR get_ordered_context_list_with_level () return the number of contexts in the list upon success or \-1 upon errors. The other functions return 0 for success or \-1 for errors. . .SH "SEE ALSO" .ad l .nh .BR selinux (8), .BR freeconary (3), .BR freecon (3), .BR security_compute_av (3), .BR getseuserbyname (3) libselinux/man/man3/get_ordered_context_list_with_level.30100644 0000000 0000000 00000000044 13756670063 022777 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/getcon.30100644 0000000 0000000 00000007002 13756670063 014753 0ustar000000000 0000000 .TH "getcon" "3" "21 December 2011" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" getcon, getprevcon, getpidcon \- get SELinux security context of a process freecon, freeconary \- free memory associated with SELinux security contexts getpeercon \- get security context of a peer socket setcon \- set current security context of a process . .SH "SYNOPSIS" .B #include .sp .BI "int getcon(char **" context ); .sp .BI "int getcon_raw(char **" context ); .sp .BI "int getprevcon(char **" context ); .sp .BI "int getprevcon_raw(char **" context ); .sp .BI "int getpidcon(pid_t " pid ", char **" context ); .sp .BI "int getpidcon_raw(pid_t " pid ", char **" context ); .sp .BI "int getpeercon(int " fd ", char **" context ); .sp .BI "int getpeercon_raw(int " fd ", char **" context ); .sp .BI "void freecon(char *" con ); .sp .BI "void freeconary(char **" con ); .sp .BI "int setcon(char *" context ); .sp .BI "int setcon_raw(char *" context ); . .SH "DESCRIPTION" .BR getcon () retrieves the context of the current process, which must be free'd with freecon. .BR getprevcon () same as getcon but gets the context before the last exec. .BR getpidcon () returns the process context for the specified PID. .BR getpeercon () retrieves context of peer socket, and set .BI * context to refer to it, which must be free'd with .BR freecon (). .BR freecon () frees the memory allocated for a security context. .BR freeconary () frees the memory allocated for a context array. If .I con is NULL, no operation is performed. .BR setcon () sets the current security context of the process to a new value. Note that use of this function requires that the entire application be trusted to maintain any desired separation between the old and new security contexts, unlike exec-based transitions performed via .BR setexeccon (3). When possible, decompose your application and use .BR setexeccon (3) and .BR execve (3) instead. Since access to file descriptors is revalidated upon use by SELinux, the new context must be explicitly authorized in the policy to use the descriptors opened by the old context if that is desired. Otherwise, attempts by the process to use any existing descriptors (including .IR stdin , .IR stdout , and .IR stderr ) after performing the .BR setcon () will fail. A multi-threaded application can perform a .BR setcon () prior to creating any child threads, in which case all of the child threads will inherit the new context. However, prior to Linux 2.6.28, .BR setcon () would fail if there are any other threads running in the same process since this would yield an inconsistency among the security contexts of threads sharing the same memory space. Since Linux 2.6.28, .BR setcon() is permitted for threads within a multi-threaded process if the new security context is bounded by the old security context, where the bounded relation is defined through typebounds statements in the policy and guarantees that the new security context has a subset of the permissions of the old security context. If the process was being ptraced at the time of the .BR setcon () operation, ptrace permission will be revalidated against the new context and the .BR setcon () will fail if it is not allowed by policy. .BR getcon_raw (), .BR getprevcon_raw (), .BR getpidcon_raw (), .BR getpeercon_raw () and .BR setcon_raw () behave identically to their non-raw counterparts but do not perform context translation. . .SH "RETURN VALUE" On error \-1 is returned. On success 0 is returned. . .SH "SEE ALSO" .BR selinux "(8), " setexeccon "(3)" libselinux/man/man3/getcon_raw.30100644 0000000 0000000 00000000022 13756670063 015617 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getexeccon.30100644 0000000 0000000 00000005547 13756670063 015634 0ustar000000000 0000000 .TH "getexeccon" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" getexeccon, setexeccon \- get or set the SELinux security context used for executing a new process rpm_execcon \- run a helper for rpm in an appropriate security context . .SH "SYNOPSIS" .B #include .sp .BI "int getexeccon(char **" context ); .sp .BI "int getexeccon_raw(char **" context ); .sp .BI "int setexeccon(char *" context ); .sp .BI "int setexeccon_raw(char *" context ); .sp .BI "int setexecfilecon(const char *" filename ", const char *" fallback_type ); .sp .BI "int rpm_execcon(unsigned int " verified ", const char *" filename ", char *const " argv "[] , char *const " envp "[]); . .SH "DESCRIPTION" .BR getexeccon () retrieves the context used for executing a new process. This returned context should be freed with .BR freecon (3) if non-NULL. .BR getexeccon () sets .BI * context to NULL if no exec context has been explicitly set by the program (i.e. using the default policy behavior). .BR setexeccon () sets the context used for the next .BR execve (2) call. NULL can be passed to .BR setexeccon () to reset to the default policy behavior. The exec context is automatically reset after the next .BR execve (2), so a program doesn't need to explicitly sanitize it upon startup. .BR setexeccon () can be applied prior to library functions that internally perform an .BR execve (2), e.g. .BR execl *(3), .BR execv *(3), .BR popen (3), in order to set an exec context for that operation. .BR getexeccon_raw () and .BR setexeccon_raw () behave identically to their non-raw counterparts but do not perform context translation. .B Note: Signal handlers that perform an .BR execve (2) must take care to save, reset, and restore the exec context to avoid unexpected behavior. .BR setexecfilecon () sets the context used for the next .BR execve (2) call, based on the policy for the .IR filename , and falling back to a new context with a .I fallback_type in case there is no transition. .BR rpm_execcon () is deprecated; please use .BR setexecfilecon () in conjunction with .BR execve (2) in all new code. This function runs a helper for rpm in an appropriate security context. The verified parameter should contain the return code from the signature verification (0 == ok, 1 == notfound, 2 == verifyfail, 3 == nottrusted, 4 == nokey), although this information is not yet used by the function. The function determines the proper security context for the helper based on policy, sets the exec context accordingly, and then executes the specified filename with the provided argument and environment arrays. . .SH "RETURN VALUE" On error \-1 is returned. On success .BR getexeccon (), .BR setexeccon () and .BR setexecfilecon () return 0. .BR rpm_execcon () only returns upon errors, as it calls .BR execve (2). . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3), " getcon "(3)" libselinux/man/man3/getexeccon_raw.30100644 0000000 0000000 00000000026 13756670063 016470 0ustar000000000 0000000 .so man3/getexeccon.3 libselinux/man/man3/getfilecon.30100644 0000000 0000000 00000003533 13756670063 015620 0ustar000000000 0000000 .TH "getfilecon" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" getfilecon, fgetfilecon, lgetfilecon \- get SELinux security context of a file . .SH "SYNOPSIS" .B #include .sp .BI "int getfilecon(const char *" path ", char **" con ); .sp .BI "int getfilecon_raw(const char *" path ", char **" con ); .sp .BI "int lgetfilecon(const char *" path ", char **" con ); .sp .BI "int lgetfilecon_raw(const char *" path ", char **" con ); .sp .BI "int fgetfilecon(int "fd ", char **" con ); .sp .BI "int fgetfilecon_raw(int "fd ", char **" con ); . .SH "DESCRIPTION" .BR getfilecon () retrieves the context associated with the given path in the file system, the length of the context is returned. .BR lgetfilecon () is identical to .BR getfilecon (), except in the case of a symbolic link, where the link itself is interrogated, not the file that it refers to. .BR fgetfilecon () is identical to .BR getfilecon (), only the open file pointed to by filedes (as returned by .BR open (2)) is interrogated in place of path. .BR getfilecon_raw (), .BR lgetfilecon_raw () and .BR fgetfilecon_raw () behave identically to their non-raw counterparts but do not perform context translation. The returned context should be freed with .BR freecon (3) if non-NULL. . .SH "RETURN VALUE" On success, a positive number is returned indicating the size of the extended attribute value. On failure, \-1 is returned and .I errno is set appropriately. If the context does not exist, or the process has no access to this attribute, .I errno is set to .BR ENODATA . If extended attributes are not supported by the filesystem, or are disabled, .I errno is set to .BR ENOTSUP . The errors documented for the .BR stat (2) system call are also applicable here. . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/getfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016463 0ustar000000000 0000000 .so man3/getfilecon.3 libselinux/man/man3/getfscreatecon.30100644 0000000 0000000 00000003333 13756670063 016473 0ustar000000000 0000000 .TH "getfscreatecon" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" getfscreatecon, setfscreatecon \- get or set the SELinux security context used for creating a new file system object . .SH "SYNOPSIS" .B #include .sp .BI "int getfscreatecon(char **" con ); .sp .BI "int getfscreatecon_raw(char **" con ); .sp .BI "int setfscreatecon(char *" context ); .sp .BI "int setfscreatecon_raw(char *" context ); . .SH "DESCRIPTION" .BR getfscreatecon () retrieves the context used for creating a new file system object. This returned context should be freed with .BR freecon (3) if non-NULL. .BR getfscreatecon () sets *con to NULL if no fscreate context has been explicitly set by the program (i.e. using the default policy behavior). .BR setfscreatecon () sets the context used for creating a new file system object. NULL can be passed to .BR setfscreatecon () to reset to the default policy behavior. The fscreate context is automatically reset after the next .BR execve (2), so a program doesn't need to explicitly sanitize it upon startup. .BR setfscreatecon () can be applied prior to library functions that internally perform an file creation, in order to set an file context on the objects. .BR getfscreatecon_raw () and .BR setfscreatecon_raw () behave identically to their non-raw counterparts but do not perform context translation. .B Note: Signal handlers that perform a .BR setfscreatecon () must take care to save, reset, and restore the fscreate context to avoid unexpected behavior. . .br .B Note: Contexts are thread specific. .SH "RETURN VALUE" On error \-1 is returned. On success 0 is returned. . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3), " getcon "(3), " getexeccon "(3)" libselinux/man/man3/getfscreatecon_raw.30100644 0000000 0000000 00000000032 13756670063 017335 0ustar000000000 0000000 .so man3/getfscreatecon.3 libselinux/man/man3/getkeycreatecon.30100644 0000000 0000000 00000003340 13756670063 016651 0ustar000000000 0000000 .TH "getkeycreatecon" "3" "9 September 2008" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" getkeycreatecon, setkeycreatecon \- get or set the SELinux security context used for creating a new kernel keyrings . .SH "SYNOPSIS" .B #include .sp .BI "int getkeycreatecon(char **" con ); .sp .BI "int getkeycreatecon_raw(char **" con ); .sp .BI "int setkeycreatecon(char *" context ); .sp .BI "int setkeycreatecon_raw(char *" context ); . .SH "DESCRIPTION" .BR getkeycreatecon () retrieves the context used for creating a new kernel keyring. This returned context should be freed with .BR freecon (3) if non-NULL. .BR getkeycreatecon () sets *con to NULL if no keycreate context has been explicitly set by the program (i.e. using the default policy behavior). .BR setkeycreatecon () sets the context used for creating a new kernel keyring. NULL can be passed to .BR setkeycreatecon () to reset to the default policy behavior. The keycreate context is automatically reset after the next .BR execve (2), so a program doesn't need to explicitly sanitize it upon startup. .BR setkeycreatecon () can be applied prior to library functions that internally perform an file creation, in order to set an file context on the objects. .BR getkeycreatecon_raw () and .BR setkeycreatecon_raw () behave identically to their non-raw counterparts but do not perform context translation. .B Note: Signal handlers that perform a .BR setkeycreatecon () must take care to save, reset, and restore the keycreate context to avoid unexpected behavior. .br .B Note: Contexts are thread specific. . .SH "RETURN VALUE" On error \-1 is returned. On success 0 is returned. . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3), " getcon "(3), " getexeccon "(3)" libselinux/man/man3/getkeycreatecon_raw.30100644 0000000 0000000 00000000033 13756670063 017516 0ustar000000000 0000000 .so man3/getkeycreatecon.3 libselinux/man/man3/getpeercon.30100644 0000000 0000000 00000000022 13756670063 015622 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getpeercon_raw.30100644 0000000 0000000 00000000022 13756670063 016473 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getpidcon.30100644 0000000 0000000 00000000022 13756670063 015443 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getpidcon_raw.30100644 0000000 0000000 00000000022 13756670063 016314 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getprevcon.30100644 0000000 0000000 00000000022 13756670063 015643 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getprevcon_raw.30100644 0000000 0000000 00000000022 13756670063 016514 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/getseuserbyname.30100644 0000000 0000000 00000001710 13756670063 016676 0ustar000000000 0000000 .TH "getseuserbyname" "3" "29 September 2005" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" getseuserbyname \- get SELinux username and level for a given Linux username . .SH "SYNOPSIS" .B #include .sp .BI "int getseuserbyname(const char *" linuxuser ", char **" selinuxuser ", char **" level "); . .SH "DESCRIPTION" .BR getseuserbyname () retrieves the SELinux username and security level associated with a given Linux username. The SELinux username and security level can then be passed to other libselinux functions such as .BR \%get_ordered_context_list_with_level (3) and .BR \%get_default_context_with_level (3). The returned SELinux username and level should be freed by the caller using free. . .SH "RETURN VALUE" On success, 0 is returned. On failure, \-1 is returned and .I errno is set appropriately. The errors documented for the .BR stat (2) system call are also applicable here. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/getsockcreatecon.30100644 0000000 0000000 00000003360 13756670063 017022 0ustar000000000 0000000 .TH "getsockcreatecon" "3" "24 September 2008" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" getsockcreatecon, setsockcreatecon \- get or set the SELinux security context used for creating a new labeled sockets . .SH "SYNOPSIS" .B #include .sp .BI "int getsockcreatecon(char **" con ); .sp .BI "int getsockcreatecon_raw(char **" con ); .sp .BI "int setsockcreatecon(char *" context ); .sp .BI "int setsockcreatecon_raw(char *" context ); . .SH "DESCRIPTION" .BR getsockcreatecon () retrieves the context used for creating a new labeled network socket. This returned context should be freed with .BR freecon (3) if non-NULL. .BR getsockcreatecon () sets *con to NULL if no sockcreate context has been explicitly set by the program (i.e. using the default policy behavior). .BR setsockcreatecon () sets the context used for creating a new labeled network sockets NULL can be passed to .BR setsockcreatecon () to reset to the default policy behavior. The sockcreate context is automatically reset after the next .BR execve (2), so a program doesn't need to explicitly sanitize it upon startup. .BR setsockcreatecon () can be applied prior to library functions that internally perform an file creation, in order to set an file context on the objects. .BR getsockcreatecon_raw () and .BR setsockcreatecon_raw () behave identically to their non-raw counterparts but do not perform context translation. .B Note: Signal handlers that perform a .BR setsockcreatecon () must take care to save, reset, and restore the sockcreate context to avoid unexpected behavior. . .br .B Note: Contexts are thread specific. .SH "RETURN VALUE" On error \-1 is returned. On success 0 is returned. . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3), " getcon "(3) libselinux/man/man3/getsockcreatecon_raw.30100644 0000000 0000000 00000000034 13756670063 017666 0ustar000000000 0000000 .so man3/getsockcreatecon.3 libselinux/man/man3/init_selinuxmnt.30100644 0000000 0000000 00000001322 13756670063 016724 0ustar000000000 0000000 .TH "init_selinuxmnt" "3" "21 Nov 2009" "" "SELinux API documentation" .SH "NAME" init_selinuxmnt \- initialize the global variable selinux_mnt . .SH "SYNOPSIS" .BI "static void init_selinuxmnt(void);" .sp .BI "static void fini_selinuxmnt(void);" .sp .BI "void set_selinuxmnt(char *" mnt ");" . .SH "DESCRIPTION" .BR init_selinuxmnt () initializes the global variable .I selinux_mnt to the selinuxfs mountpoint. .BR fini_selinuxmnt () deinitializes the global variable .I selinux_mnt that stores the selinuxfs mountpoint. .BR set_selinuxmnt () changes the selinuxfs mountpoint to .IR mnt . . .SH "AUTHOR" This manual page has been written by Guido Trentalancia . .SH "SEE ALSO" .BR selinux (8), libselinux/man/man3/is_context_customizable.30100644 0000000 0000000 00000001545 13756670063 020442 0ustar000000000 0000000 .TH "is_context_customizable" "3" "10 January 2005" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" is_context_customizable \- check whether SELinux context type is customizable by the administrator . .SH "SYNOPSIS" .B #include .sp .BI "int is_context_customizable(char *" scon ); . .SH "DESCRIPTION" This function checks whether the type of scon is in the .I /etc/selinux/{SELINUXTYPE}/context/customizable_types file. A customizable type is a file context type that administrators set on files, usually to allow certain domains to share the file content. restorecon and setfiles, by default, leave these context in place. . .SH "RETURN VALUE" Returns 1 if security context is customizable or 0 if it is not. Returns \-1 on error. . .SH "FILE" .I /etc/selinux/{SELINUXTYPE}/context/customizable_types . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/is_selinux_enabled.30100644 0000000 0000000 00000001327 13756670063 017334 0ustar000000000 0000000 .TH "is_selinux_enabled" "3" "7 Mar 2010" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" is_selinux_enabled \- check whether SELinux is enabled . .SH "NAME" is_selinux_mls_enabled \- check whether SELinux is enabled for (Multi Level Security) MLS . .SH "SYNOPSIS" .B #include .sp .B int is_selinux_enabled(); .sp .B int is_selinux_mls_enabled(); . .SH "DESCRIPTION" .BR is_selinux_enabled () returns 1 if SELinux is running or 0 if it is not. On error, \-1 is returned. .BR is_selinux_mls_enabled () returns 1 if SELinux is capable of running in MLS mode or 0 if it is not. To determine the policy in use on the system, use .BR selinux_getpolicytype (3). . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/is_selinux_mls_enabled.30100644 0000000 0000000 00000000036 13756670063 020203 0ustar000000000 0000000 .so man3/is_selinux_enabled.3 libselinux/man/man3/lgetfilecon.30100644 0000000 0000000 00000000026 13756670063 015766 0ustar000000000 0000000 .so man3/getfilecon.3 libselinux/man/man3/lgetfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016637 0ustar000000000 0000000 .so man3/getfilecon.3 libselinux/man/man3/lsetfilecon.30100644 0000000 0000000 00000000026 13756670063 016002 0ustar000000000 0000000 .so man3/setfilecon.3 libselinux/man/man3/lsetfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016653 0ustar000000000 0000000 .so man3/setfilecon.3 libselinux/man/man3/manual_user_enter_context.30100644 0000000 0000000 00000000044 13756670063 020747 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/matchmediacon.30100644 0000000 0000000 00000001371 13756670063 016273 0ustar000000000 0000000 .TH "matchmediacon" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" matchmediacon \- get the default SELinux security context for the specified mediatype from the policy . .SH "SYNOPSIS" .B #include .sp .BI "int matchmediacon(const char *" media ", char **" con ); . .SH "DESCRIPTION" .BR matchmediacon () matches the specified media type with the media contexts configuration and sets the security context .I con to refer to the resulting context. .sp .B Note: Caller must free returned security context .I con using .BR freecon (3). . .SH "RETURN VALUE" Returns 0 on success or \-1 otherwise. . .SH Files .I /etc/selinux/{POLICYTYPE}/contexts/files/media . .SH "SEE ALSO" .BR selinux "(8), " freecon "(3) libselinux/man/man3/matchpathcon.30100644 0000000 0000000 00000007076 13756670063 016160 0ustar000000000 0000000 .TH "matchpathcon" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" .SH "NAME" matchpathcon, matchpathcon_index \- get the default SELinux security context for the specified path from the file contexts configuration . .SH "SYNOPSIS" .B #include .sp .BI "int matchpathcon_init(const char *" path ");" .sp .BI "int matchpathcon_init_prefix(const char *" path ", const char *" prefix ");" .sp .BI "int matchpathcon_fini(void);" .sp .BI "int matchpathcon(const char *" path ", mode_t " mode ", char **" con "); .sp .BI "int matchpathcon_index(const char *" name ", mode_t " mode ", char **" con ");" . .SH "DESCRIPTION" This family of functions is deprecated. For new code, please use .BR selabel_open (3) with the .B SELABEL_CTX_FILE backend in place of .BR matchpathcon_init (), use .BR selabel_close (3) in place of .BR matchpathcon_fini (), and use .BR selabel_lookup (3) in place of .BR matchpathcon (). The remaining description below is for the legacy interface. .BR matchpathcon_init () loads the file contexts configuration specified by .I path into memory for use by subsequent .BR matchpathcon () calls. If .I path is NULL, then the active file contexts configuration is loaded by default, i.e. the path returned by .BR selinux_file_context_path (3). Unless the .B MATCHPATHCON_BASEONLY flag has been set via .BR \%set_matchpathcon_flags (3), files with the same path prefix but a .B \%.homedirs and .B .local suffix are also looked up and loaded if present. These files provide dynamically generated entries for user home directories and for local customizations. .BR matchpathcon_init_prefix () is the same as .BR matchpathcon_init () but only loads entries with regular expressions whose first pathname component is a prefix of .I \%prefix , e.g. pass "/dev" if you only intend to call .BR matchpathcon () with pathnames beginning with /dev. However, this optimization is no longer necessary due to the use of .I file_contexts.bin files with precompiled regular expressions, so use of this interface is deprecated. .BR matchpathcon_fini () frees the memory allocated by a prior call to .BR matchpathcon_init. () This function can be used to free and reset the internal state between multiple .BR matchpathcon_init () calls, or to free memory when finished using .BR matchpathcon (). .BR matchpathcon () matches the specified .I pathname, after transformation via .BR realpath (3) excepting any final symbolic link component if S_IFLNK was specified as the .I mode, and .I mode against the .I file contexts configuration and sets the security context .I con to refer to the resulting context. The caller must free the returned security context .I con using .BR freecon (3) when finished using it. .I mode can be 0 to disable mode matching, but should be provided whenever possible, as it may affect the matching. Only the file format bits (i.e. the file type) of the .I mode are used. If .BR matchpathcon_init () has not already been called, then this function will call it upon its first invocation with a NULL .I path, defaulting to the active file contexts configuration. .BR matchpathcon_index () is the same as .BR matchpathcon () but returns a specification index that can later be used in a .BR matchpathcon_filespec_add (3) call. . .SH "RETURN VALUE" Returns zero on success or \-1 otherwise. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " set_matchpathcon_flags "(3), " set_matchpathcon_invalidcon "(3), " set_matchpathcon_printf "(3), " matchpathcon_filespec_add "(3), " matchpathcon_checkmatches "(3), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/matchpathcon_checkmatches.30100644 0000000 0000000 00000003273 13756670063 020655 0ustar000000000 0000000 .TH "matchpathcon_checkmatches" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" .SH "NAME" matchpathcon_checkmatches, matchpathcon_filespec_add, matchpathcon_filespec_destroy, matchpathcon_filespec_eval \- check and report whether any specification index has no matches with any inode. Maintenance and statistics on inode associations . .SH "SYNOPSIS" .B #include .sp .BI "void matchpathcon_checkmatches(char *" str ");" .sp .BI "int matchpathcon_filespec_add(ino_t " ino ", int " specind ", const char *" file ");" .sp .BI "void matchpathcon_filespec_destroy(void);" .sp .BI "void matchpathcon_filespec_eval(void);" . .SH "DESCRIPTION" .BR matchpathcon_checkmatches () checks whether any specification has no matches and reports them. The .I str argument is used as a prefix for any warning messages. .sp .BR matchpathcon_filespec_add () maintains an association between an inode .I ino and a specification index .IR specind , and checks whether a conflicting specification is already associated with the same inode (e.g. due to multiple hard links). If so, then it uses the latter of the two specifications based on their order in the .I file context configuration. Returns the specification index used or \-1 on error. .sp .BR matchpathcon_filespec_destroy () destroys any inode associations that have been added, e.g. to restart for a new filesystem. .sp .BR matchpathcon_filespec_eval () displays statistics on the hash table usage for the inode associations. . .SH "RETURN VALUE" Returns zero on success or \-1 otherwise. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " matchpathcon "(3), " matchpathcon_index "(3), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/matchpathcon_filespec_add.30100644 0000000 0000000 00000000045 13756670063 020627 0ustar000000000 0000000 .so man3/matchpathcon_checkmatches.3 libselinux/man/man3/matchpathcon_filespec_destroy.30100644 0000000 0000000 00000000045 13756670063 021570 0ustar000000000 0000000 .so man3/matchpathcon_checkmatches.3 libselinux/man/man3/matchpathcon_filespec_eval.30100644 0000000 0000000 00000000045 13756670063 021026 0ustar000000000 0000000 .so man3/matchpathcon_checkmatches.3 libselinux/man/man3/matchpathcon_fini.30100644 0000000 0000000 00000000030 13756670063 017144 0ustar000000000 0000000 .so man3/matchpathcon.3 libselinux/man/man3/matchpathcon_index.30100644 0000000 0000000 00000000030 13756670063 017326 0ustar000000000 0000000 .so man3/matchpathcon.3 libselinux/man/man3/matchpathcon_init.30100644 0000000 0000000 00000000030 13756670063 017162 0ustar000000000 0000000 .so man3/matchpathcon.3 libselinux/man/man3/mode_to_security_class.30100644 0000000 0000000 00000000044 13756670063 020235 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man3/print_access_vector.30100644 0000000 0000000 00000000044 13756670063 017532 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man3/query_user_context.30100644 0000000 0000000 00000000044 13756670063 017442 0ustar000000000 0000000 .so man3/get_ordered_context_list.3 libselinux/man/man3/rpm_execcon.30100644 0000000 0000000 00000000026 13756670063 015775 0ustar000000000 0000000 .so man3/getexeccon.3 libselinux/man/man3/security_av_perm_to_string.30100644 0000000 0000000 00000000044 13756670063 021143 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man3/security_av_string.30100644 0000000 0000000 00000000044 13756670063 017416 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man3/security_check_context.30100644 0000000 0000000 00000001172 13756670063 020246 0ustar000000000 0000000 .TH "security_check_context" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" security_check_context \- check the validity of a SELinux context . .SH "SYNOPSIS" .B #include .sp .BI "int security_check_context(char *" con ); .sp .BI "int security_check_context_raw(char *" con ); . .SH "DESCRIPTION" .BR security_check_context () returns 0 if SELinux is running and the context is valid, otherwise it returns \-1. .BR security_check_context_raw () behaves identically to .BR \%security_check_context () but does not perform context translation. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/security_check_context_raw.30100644 0000000 0000000 00000000042 13756670063 021112 0ustar000000000 0000000 .so man3/security_check_context.3 libselinux/man/man3/security_class_to_string.30100644 0000000 0000000 00000005442 13756670063 020626 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "security_class_to_string" "3" "30 Mar 2007" "" "SELinux API documentation" .SH "NAME" security_class_to_string, security_av_perm_to_string, string_to_security_class, string_to_av_perm, security_av_string, mode_to_security_class \- convert between SELinux class and permission values and string names. . print_access_vector \- display an access vector in human-readable form. . .SH "SYNOPSIS" .B #include .sp .BI "const char *security_class_to_string(security_class_t " tclass ");" .sp .BI "const char *security_av_perm_to_string(security_class_t " tclass ", access_vector_t " av ");" .sp .BI "int security_av_string(security_class_t " tclass ", access_vector_t " av ", char **" result ");" .sp .BI "security_class_t string_to_security_class(const char *" name ");" .sp .BI "security_class_t mode_to_security_class(mode_t " mode ");" .sp .BI "access_vector_t string_to_av_perm(security_class_t " tclass ", const char *" name ");" .sp .BI "void print_access_vector(security_class_t " tclass ", access_vector_t " av ");" . .SH "DESCRIPTION" .BR security_class_to_string () returns a string name for class .IR tclass , or NULL if the class is invalid. The returned string must not be modified or freed. .BR security_av_perm_to_string () returns a string name for the access vector bit .I av of class .IR tclass , or NULL if either argument is invalid. The returned string must not be modified or freed. .BR security_av_string () computes a full access vector string representation using .I tclass and .IR av , which may have multiple bits set. The string is returned in the memory pointed to by .IR result , and should be freed by the caller using .BR free (3). .BR string_to_security_class () returns the class value corresponding to the string name .IR name , or zero if no such class exists. .BR mode_to_security_class () returns the class value corresponding to the specified .IR mode , or zero if no such class exists. .BR string_to_av_perm () returns the access vector bit corresponding to the string name .I name and security class .IR tclass , or zero if no such value exists. .BR print_access_vector () displays an access vector in human-readable form on the standard output stream. . .SH "RETURN VALUE" .BR security_av_string () returns zero on success or \-1 on error with .I errno set appropriately. .BR print_access_vector () does not return a value. All other functions return zero or NULL on error. . .SH "ERRORS" .TP .B EINVAL A class or access vector argument is not recognized by the currently loaded policy. .TP .B ENOMEM An attempt to allocate memory failed. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR selinux (8), .BR getcon (3), .BR getfilecon (3) .BR stat (3) libselinux/man/man3/security_commit_booleans.30100644 0000000 0000000 00000000042 13756670063 020572 0ustar000000000 0000000 .so man3/security_load_booleans.3 libselinux/man/man3/security_compute_av.30100644 0000000 0000000 00000012512 13756670063 017567 0ustar000000000 0000000 .TH "security_compute_av" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" security_compute_av, security_compute_av_flags, security_compute_create, security_compute_create_name, security_compute_relabel, security_compute_member, security_compute_user, security_get_initial_context \- query the SELinux policy database in the kernel . .SH "SYNOPSIS" .B #include .sp .BI "int security_compute_av(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp .BI "int security_compute_av_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp .BI "int security_compute_av_flags(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp .BI "int security_compute_av_flags_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp .BI "int security_compute_create(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_create_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_create_name(char *" scon ", char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); .sp .BI "int security_compute_create_name_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); .sp .BI "int security_compute_relabel(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_relabel_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_member(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_member_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp .BI "int security_compute_user(char *" scon ", const char *" username ", char ***" con ); .sp .BI "int security_compute_user_raw(char *" scon ", const char *" username ", char ***" con ); .sp .BI "int security_get_initial_context(const char *" name ", char **" con ); .sp .BI "int security_get_initial_context_raw(const char *" name ", char **" con ); .sp .BI "int selinux_check_access(const char *" scon ", const char *" tcon ", const char *" class ", const char *" perm ", void *" auditdata); .sp .BI "int selinux_check_passwd_access(access_vector_t " requested ); .sp .BI "int checkPasswdAccess(access_vector_t " requested ); . .SH "DESCRIPTION" .BR security_compute_av () queries whether the policy permits the source context .I scon to access the target context .I tcon via class .I tclass with the .I requested access vector. The decision is returned in .IR avd . .BR security_compute_av_flags () is identical to .B security_compute_av but additionally sets the .I flags field of .IR avd . Currently one flag is supported: .BR SELINUX_AVD_FLAGS_PERMISSIVE , which indicates the decision is computed on a permissive domain. .BR security_compute_create () is used to compute a context to use for labeling a new object in a particular class based on a SID pair. .BR security_compute_create_name () is identical to .BR \%security_compute_create () but also takes name of the new object in creation as an argument. When .B TYPE_TRANSITION rule on the given class and a SID pair has object name extension, we shall be able to obtain a correct .I newcon according to the security policy. Note that this interface is only supported on the linux 2.6.40 or later. In the older kernel, the object name will be simply ignored. .BR security_compute_relabel () is used to compute the new context to use when relabeling an object, it is used in the pam_selinux.so source and the newrole source to determine the correct label for the tty at login time, but can be used for other things. .BR security_compute_member () is used to compute the context to use when labeling a polyinstantiated object instance. .BR security_compute_user () is used to determine the set of user contexts that can be reached from a source context. It is mainly used by .BR get_ordered_context_list (). .BR security_get_initial_context () is used to get the context of a kernel initial security identifier specified by .I name .BR security_compute_av_raw (), .BR security_compute_av_flags_raw (), .BR \%security_compute_create_raw (), .BR \%security_compute_create_name_raw (), .BR \%security_compute_relabel_raw (), .BR \%security_compute_member_raw (), .BR \%security_compute_user_raw () and .BR \%security_get_initial_context_raw () behave identically to their non-raw counterparts but do not perform context translation. .BR selinux_check_access () is used to check if the source context has the access permission for the specified class on the target context. .BR selinux_check_passwd_access () is used to check for a permission in the .I passwd class. .BR selinux_check_passwd_access () uses getprevcon() for the source and target security contexts. .BR checkPasswdAccess () is a deprecated alias of the .BR selinux_check_passwd_access () function. . .SH "RETURN VALUE" Returns zero on success or \-1 on error. . .SH "SEE ALSO" .BR selinux "(8), " getcon "(3), " getfilecon "(3), " get_ordered_context_list "(3)" libselinux/man/man3/security_compute_av_flags.30100644 0000000 0000000 00000000037 13756670063 020742 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_av_flags_raw.30100644 0000000 0000000 00000000037 13756670063 021613 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_av_raw.30100644 0000000 0000000 00000000037 13756670063 020437 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_create.30100644 0000000 0000000 00000000037 13756670063 020423 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_create_name.30100644 0000000 0000000 00000000037 13756670063 021423 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_create_name_raw.30100644 0000000 0000000 00000000037 13756670063 022274 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_create_raw.30100644 0000000 0000000 00000000037 13756670063 021274 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_member.30100644 0000000 0000000 00000000037 13756670063 020427 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_member_raw.30100644 0000000 0000000 00000000037 13756670063 021300 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_relabel.30100644 0000000 0000000 00000000037 13756670063 020566 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_relabel_raw.30100644 0000000 0000000 00000000037 13756670063 021437 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_user.30100644 0000000 0000000 00000000037 13756670063 020136 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_compute_user_raw.30100644 0000000 0000000 00000000037 13756670063 021007 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_deny_unknown.30100644 0000000 0000000 00000000037 13756670063 020142 0ustar000000000 0000000 .so man3/security_getenforce.3 libselinux/man/man3/security_disable.30100644 0000000 0000000 00000001547 13756670063 017036 0ustar000000000 0000000 .TH "security_disable" "3" "21 Nov 2009" "" "SELinux API documentation" .SH "NAME" security_disable \- disable the SELinux kernel code at runtime . .SH "SYNOPSIS" .B #include .sp .BI "int security_disable(void);" . .SH "DESCRIPTION" .BR security_disable () disables the SELinux kernel code, unregisters selinuxfs from .IR /proc/filesystems , and then unmounts .IR /sys/fs/selinux . .sp This function can only be called at runtime and prior to the initial policy load. After the initial policy load, the SELinux kernel code cannot be disabled, but only placed in "permissive" mode by using .BR security_setenforce(3). . .SH "RETURN VALUE" .BR security_disable () returns zero on success or \-1 on error. . .SH "AUTHOR" This manual page has been written by Guido Trentalancia . .SH "SEE ALSO" .BR selinux (8), " setenforce "(8) libselinux/man/man3/security_get_boolean_active.30100644 0000000 0000000 00000000042 13756670063 021231 0ustar000000000 0000000 .so man3/security_load_booleans.3 libselinux/man/man3/security_get_boolean_names.30100644 0000000 0000000 00000000042 13756670063 021061 0ustar000000000 0000000 .so man3/security_load_booleans.3 libselinux/man/man3/security_get_boolean_pending.30100644 0000000 0000000 00000000042 13756670063 021402 0ustar000000000 0000000 .so man3/security_load_booleans.3 libselinux/man/man3/security_get_initial_context.30100644 0000000 0000000 00000000037 13756670063 021460 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_get_initial_context_raw.30100644 0000000 0000000 00000000037 13756670063 022331 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/security_getenforce.30100644 0000000 0000000 00000004032 13756670063 017544 0ustar000000000 0000000 .TH "security_getenforce" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" security_getenforce, security_setenforce, security_deny_unknown, security_reject_unknown, security_get_checkreqprot \- get or set the enforcing state of SELinux . .SH "SYNOPSIS" .B #include .sp .B int security_getenforce(void); .sp .BI "int security_setenforce(int "value ); .sp .B int security_deny_unknown(void); .sp .B int security_reject_unknown(void); .sp .B int security_get_checkreqprot(void); . .SH "DESCRIPTION" .BR security_getenforce () returns 0 if SELinux is running in permissive mode, 1 if it is running in enforcing mode, and \-1 on error. .BR security_setenforce () sets SELinux to enforcing mode if the value 1 is passed in, and sets it to permissive mode if 0 is passed in. On success 0 is returned, on error \-1 is returned. .BR security_deny_unknown () returns 0 if SELinux treats policy queries on undefined object classes or permissions as being allowed, 1 if such queries are denied, and \-1 on error. .BR security_reject_unknown () returns 1 if the current policy was built with handle-unknown=reject and SELinux would reject loading it, if it did not define all kernel object classes and permissions. In this state, when .BR selinux_set_mapping() and .BR selinux_check_access() are used with an undefined userspace class or permission, an error is returned and errno is set to EINVAL. It returns 0 if the current policy was built with handle-unknown=allow or handle-unknown=deny. In this state, policy queries are treated according to .BR security_deny_unknown(). \-1 is returned on error. .BR security_get_checkreqprot () can be used to determine whether SELinux is configured to check the protection requested by the application or the actual protection that will be applied by the kernel (including the effects of READ_IMPLIES_EXEC) on mmap and mprotect calls. It returns 0 if SELinux checks the actual protection, 1 if it checks the requested protection, and \-1 on error. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/security_load_booleans.30100644 0000000 0000000 00000004306 13756670063 020230 0ustar000000000 0000000 .TH "security_get_boolean_names" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation" .SH "NAME" security_load_booleans, security_set_boolean, security_commit_booleans, security_get_boolean_names, security_get_boolean_active, security_get_boolean_pending \- routines for manipulating SELinux boolean values . .SH "SYNOPSIS" .B #include .sp .BI "int security_load_booleans(char *" path ");" .sp .BI "int security_get_boolean_names(char ***" names ", int *" len ");" .sp .BI "int security_get_boolean_pending(const char *" name ");" .sp .BI "int security_get_boolean_active(const char *" name ");" .sp .BI "int security_set_boolean(const char *" name ", int " value ");" .sp .BI "int security_set_boolean_list(size_t " boolcnt ", SELboolean *" boollist ", int " permanent ");" .sp .BI "int security_commit_booleans(void);" . .SH "DESCRIPTION" The SELinux policy can include conditional rules that are enabled or disabled based on the current values of a set of policy booleans. These policy booleans allow runtime modification of the security policy without having to load a new policy. The SELinux API allows for a transaction based update. So you can set several boolean values and then commit them all at once. .BR security_load_booleans () loads policy boolean settings. Path may be NULL, in which case the booleans are loaded from the active policy boolean configuration file. .BR security_get_boolean_names () provides a list of boolean names, currently supported by the loaded policy. .BR security_get_boolean_pending () returns the pending value for boolean or \-1 on failure. .BR security_get_boolean_active () returns the active value for boolean or \-1 on failure. .BR security_set_boolean () sets the pending value for boolean .BR security_set_boolean_list () saves a list of booleans in a single transaction. .BR security_commit_booleans () commits all pending values for the booleans. . .SH "RETURN VALUE" Where not otherwise stated, functions described in this manual page return zero on success or \-1 on error. . .SH AUTHOR This manual page was written by Dan Walsh . . .SH "SEE ALSO" .BR selinux (8), .BR getsebool (8), .BR booleans (8), .BR togglesebool (8) libselinux/man/man3/security_load_policy.30100644 0000000 0000000 00000004276 13756670063 017733 0ustar000000000 0000000 .TH "security_load_policy" "3" "3 November 2009" "guido@trentalancia.com" "SELinux API documentation" .SH "NAME" security_load_policy \- load a new SELinux policy . .SH "SYNOPSIS" .B #include .sp .BI "int security_load_policy(void *" data ", size_t "len ); .sp .BI "int selinux_mkload_policy(int " preservebools ");" .sp .BI "int selinux_init_load_policy(int *" enforce ");" . .SH "DESCRIPTION" .BR security_load_policy () loads a new policy, returns 0 for success and \-1 for error. .BR selinux_mkload_policy () makes a policy image and loads it. This function provides a higher level interface for loading policy than .BR \%security_load_policy (), internally determining the right policy version, locating and opening the policy file, mapping it into memory, manipulating it as needed for current boolean settings and/or local definitions, and then calling security_load_policy to load it. .I preservebools is a boolean flag indicating whether current policy boolean values should be preserved into the new policy (if 1) or reset to the saved policy settings (if 0). The former case is the default for policy reloads, while the latter case is an option for policy reloads but is primarily used for the initial policy load. .BR selinux_init_load_policy () performs the initial policy load. This function determines the desired enforcing mode, sets the .I enforce argument accordingly for the caller to use, sets the SELinux kernel enforcing status to match it, and loads the policy. It also internally handles the initial selinuxfs mount required to perform these actions. .sp It should also be noted that after the initial policy load, the SELinux kernel code cannot anymore be disabled and the selinuxfs cannot be unmounted using a call to .BR security_disable (3). Therefore, after the initial policy load, the only operational changes are those permitted by .BR security_setenforce (3) (i.e. eventually setting the framework in permissive mode rather than in enforcing one). . .SH "RETURN VALUE" Returns zero on success or \-1 on error. . .SH "AUTHOR" This manual page has been written by Guido Trentalancia . .SH "SEE ALSO" .BR selinux "(8), " security_disable "(3), " setenforce "(8) libselinux/man/man3/security_mkload_policy.30100644 0000000 0000000 00000000040 13756670063 020244 0ustar000000000 0000000 .so man3/security_load_policy.3 libselinux/man/man3/security_policyvers.30100644 0000000 0000000 00000000641 13756670063 017624 0ustar000000000 0000000 .TH "security_policyvers" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" security_policyvers \- get the version of the SELinux policy .SH "SYNOPSIS" .B #include .sp .B int security_policyvers(); . .SH "DESCRIPTION" .BR security_policyvers () returns the version of the policy (a positive integer) on success, or \-1 on error. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/security_reject_unknown.30100644 0000000 0000000 00000000037 13756670063 020457 0ustar000000000 0000000 .so man3/security_getenforce.3 libselinux/man/man3/security_set_boolean.30100644 0000000 0000000 00000000042 13756670063 017712 0ustar000000000 0000000 .so man3/security_load_booleans.3 libselinux/man/man3/security_setenforce.30100644 0000000 0000000 00000000032 13756670063 017554 0ustar000000000 0000000 .so security_getenforce.3 libselinux/man/man3/selabel_close.30100644 0000000 0000000 00000000030 13756670063 016262 0ustar000000000 0000000 .so man3/selabel_open.3 libselinux/man/man3/selabel_digest.30100644 0000000 0000000 00000002457 13756670063 016453 0ustar000000000 0000000 .TH "selabel_digest" "3" "16 Sept 2015" "" "SELinux API documentation" .SH "NAME" selabel_digest \- Return digest of specfiles and list of files used . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int selabel_digest(struct selabel_handle *" hnd , .in +\w'int selabel_digest('u .BI "unsigned char **" digest , .BI "size_t *" digest_len , .br .BI "char ***" specfiles, .BI "size_t *" num_specfiles ");" .in . .SH "DESCRIPTION" .BR selabel_digest () performs an operation on the handle .IR hnd , returning the results of the SHA1 digest pointed to by .IR digest , whose length will be .IR digest_len . The list of specfiles used in the SHA1 digest calculation is returned in .I specfiles with the number of entries in .IR num_specfiles . .sp To enable .BR selabel_digest () to return this information the .B SELABEL_OPT_DIGEST option must be enable in .BR selabel_open (3). .sp The result of .BR selabel_digest () must not be used after .BR selabel_close (3). . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B EINVAL No digest available (returned if .B SELABEL_OPT_DIGEST option not enabled). .TP .B ENOMEM An attempt to allocate memory failed. . .SH "SEE ALSO" .BR selabel_open (3), .BR selinux (8) libselinux/man/man3/selabel_lookup.30100644 0000000 0000000 00000003233 13756670063 016476 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_lookup" "3" "18 Jun 2007" "" "SELinux API documentation" .SH "NAME" selabel_lookup \- obtain SELinux security context from a string label . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" key ", int " type ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup_raw('u .BI "char **" context , .br .BI "const char *" key ", int " type ");" .in . .SH "DESCRIPTION" .BR selabel_lookup () performs a lookup operation on the handle .IR hnd , returning the result in the memory pointed to by .IR context , which must be freed by the caller using .BR freecon (3). The .I key and .I type parameters are the inputs to the lookup operation and are interpreted according to the specific backend that .I handle is open on. .BR selabel_lookup_raw () behaves identically to .BR selabel_lookup () but does not perform context translation. . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B ENOENT No context corresponding to the input .I key and .I type was found. .TP .B EINVAL The .I key and/or .I type inputs are invalid, or the context being returned failed validation. .TP .B ENOMEM An attempt to allocate memory failed. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR selabel_open (3), .BR selabel_stats (3), .BR selinux_set_callback (3), .BR selinux (8) libselinux/man/man3/selabel_lookup_best_match.30100644 0000000 0000000 00000005141 13756670063 020667 0ustar000000000 0000000 .TH "selabel_lookup_best_match" "3" "05 May 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_lookup_best_match \- obtain a best match SELinux security context \- Only supported on file backend. . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "int selabel_lookup_best_match(struct selabel_handle *" hnd , .in +\w'int selabel_lookup_best_match('u .BI "char **" context , .br .BI "const char *" key , .br .BI "const char **" links , .br .BI "int " type ");" .in .sp .BI "int selabel_lookup_best_match_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup_best_match_raw('u .BI "char **" context , .br .BI "const char *" key , .br .BI "const char **" links , .br .BI "int " type ");" .in . .SH "DESCRIPTION" .BR selabel_lookup_best_match () performs a best match lookup operation on the handle .IR hnd , returning the result in the memory pointed to by .IR context , which must be freed by the caller using .BR freecon (3). The \fIkey\fR parameter is a file path to check for best match using zero or more \fIlink\fR (aliases) parameters. The order of precedence for best match is: .RS .IP "1." 4 An exact match for the real path (\fIkey\fR) or .IP "2." 4 An exact match for any of the \fIlink\fRs (aliases), or .IP "3." 4 The longest fixed prefix match. .RE .sp The \fItype\fR parameter is an optional file \fImode\fR argument that should be set to the mode bits of the file, as determined by \fBlstat\fR(2). \fImode\fR may be zero, however full matching may not occur. .BR selabel_lookup_best_match_raw () behaves identically to .BR selabel_lookup_best_match () but does not perform context translation. . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B ENOENT No context corresponding to the input .I key and .I type was found. .TP .B EINVAL The .I key and/or .I type inputs are invalid, or the context being returned failed validation. .TP .B ENOMEM An attempt to allocate memory failed. .sp .SH "NOTES" Example usage - When a service creates a device node, it may also create one or more symlinks to the device node. These symlinks may be the only stable name for the device, e.g. if the partition is dynamically assigned. The file label backend supports this by looking up the "best match" for a device node based on its real path (\fIkey\fR) and any \fIlink\fRs to it (aliases). The order of precedence for best match is described above. .sp .SH "SEE ALSO" .BR selabel_open (3), .BR selabel_stats (3), .BR selinux_set_callback (3), .BR selinux (8), .BR lstat (2), .BR selabel_file (5) libselinux/man/man3/selabel_lookup_best_match_raw.30100644 0000000 0000000 00000000045 13756670063 021536 0ustar000000000 0000000 .so man3/selabel_lookup_best_match.3 libselinux/man/man3/selabel_lookup_raw.30100644 0000000 0000000 00000000032 13756670063 017341 0ustar000000000 0000000 .so man3/selabel_lookup.3 libselinux/man/man3/selabel_open.30100644 0000000 0000000 00000005471 13756670063 016134 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_open" "3" "18 Jun 2007" "" "SELinux API documentation" .SH "NAME" selabel_open, selabel_close \- userspace SELinux labeling interface . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "struct selabel_handle *selabel_open(int " backend , .in +\w'struct selabel_handle *selabel_open('u .BI "const struct selinux_opt *" options , .br .BI "unsigned " nopt ");" .in .sp .BI "void selabel_close(struct selabel_handle *" hnd ");" . .SH "DESCRIPTION" .BR selabel_open () is used to initialize a labeling handle to be used for lookup operations. The .I backend argument specifies which backend is to be opened; the list of current backends appears in .B BACKENDS below. The .I options argument should be NULL or a pointer to an array of .B selinux_opt structures of length .IR nopt : .RS .ta 4n 16n 24n .nf struct selinux_opt { int type; const char *value; }; .fi .ta .RE The available option types are described in .B GLOBAL OPTIONS below as well as in the documentation for each individual backend. The return value on success is a non-NULL value for use in subsequent label operations. .BR selabel_close () terminates use of a handle, freeing any internal resources associated with it. After this call has been made, the handle must not be used again. . .SH "GLOBAL OPTIONS" Global options which may be passed to .BR selabel_open () include the following: . .TP .B SELABEL_OPT_UNUSED The option with a type code of zero is a no-op. Thus an array of options may be initizalized to zero and any untouched elements will not cause an error. .TP .B SELABEL_OPT_VALIDATE A non-null value for this option enables context validation. By default, .BR security_check_context (3) is used; a custom validation function can be provided via .BR selinux_set_callback (3). Note that an invalid context may not be treated as an error unless it is actually encountered during a lookup operation. .TP .B SELABEL_OPT_DIGEST A non-null value for this option enables the generation of an SHA1 digest of the spec files loaded as described in .BR selabel_digest (3) . .SH "BACKENDS" .TP .B SELABEL_CTX_FILE File contexts backend, described in .BR selabel_file (5). .TP .B SELABEL_CTX_MEDIA Media contexts backend, described in .BR selabel_media (5). .TP .B SELABEL_CTX_X X Windows contexts backend, described in .BR selabel_x (5). .TP .B SELABEL_CTX_DB Database objects contexts backend, described in .BR selabel_db (5). . .SH "RETURN VALUE" A non-NULL handle value is returned on success. On error, NULL is returned and .I errno is set appropriately. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .ad l .nh .BR selabel_lookup (3), .BR selabel_stats (3), .BR selinux_set_callback (3), .BR selinux (8) libselinux/man/man3/selabel_partial_match.30100644 0000000 0000000 00000001637 13756670063 020003 0ustar000000000 0000000 .TH "selabel_partial_match" "3" "05 May 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_partial_match \- determine whether a direct or partial match is possible on a file path \- Only supported on file backend. . .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .sp .BI "bool selabel_partial_match(struct selabel_handle *" hnd , .in +\w'int selabel_partial_match('u .BI "const char *" key ");" .in . .SH "DESCRIPTION" .BR selabel_partial_match () performs a partial match operation on the handle .IR hnd , returning TRUE or FALSE. The \fIkey\fR parameter is a file path to check for a direct or partial match. .sp .SH "RETURN VALUE" TRUE is returned if a direct or partial match is found, FALSE if not. .sp .SH "SEE ALSO" .BR selabel_open (3), .BR selabel_stats (3), .BR selinux_set_callback (3), .BR selinux (8), .BR selabel_file (5) libselinux/man/man3/selabel_stats.30100644 0000000 0000000 00000001656 13756670063 016332 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_stats" "3" "18 Jun 2007" "" "SELinux API documentation" .SH "NAME" selabel_stats \- obtain SELinux labeling statistics . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "void selabel_stats(struct selabel_handle *" hnd ");" . .SH "DESCRIPTION" .BR selabel_stats () causes zero or more messages to be printed containing backend-specific information about number of queries performed, number of unused entries, or other operational information. The messages are printed to standard error by default; a custom logging function can be provided via .BR selinux_set_callback (3). . .SH "RETURN VALUE" None. . .SH "ERRORS" None. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR selabel_open (3), .BR selabel_lookup (3), .BR selinux_set_callback (3), .BR selinux (8) libselinux/man/man3/selinux_binary_policy_path.30100644 0000000 0000000 00000006726 13756670063 021136 0ustar000000000 0000000 .TH "selinux_binary_policy_path" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation" .SH "NAME" selinux_path, selinux_policy_root, selinux_binary_policy_path, selinux_current_policy_path, selinux_failsafe_context_path, selinux_removable_context_path, selinux_default_context_path, selinux_user_contexts_path, selinux_file_context_path, selinux_media_context_path, selinux_contexts_path, selinux_booleans_path \- These functions return the paths to the active SELinux policy configuration directories and files . .SH "SYNOPSIS" .B #include .sp .B const char *selinux_path(void); .sp .B const char *selinux_policy_root(void); .sp .B const char *selinux_binary_policy_path(void); .sp .B const char *selinux_current_policy_path(void); .sp .B const char *selinux_failsafe_context_path(void); .sp .B const char *selinux_removable_context_path(void); .sp .B const char *selinux_default_context_path(void); .sp .B const char *selinux_user_contexts_path(void); .sp .B const char *selinux_usersconf_path(void); .sp .B const char *selinux_x_context_path(void); .sp .B const char *selinux_sepgsql_context_path(void); .sp .B const char *selinux_file_context_path(void); .sp .B const char *selinux_media_context_path(void); .sp .B const char *selinux_securetty_types_path(void); .sp .B const char *selinux_contexts_path(void); .sp .B const char *selinux_booleans_path(void); . .SH "DESCRIPTION" These functions return the paths to the active policy configuration directories and files based on the settings in .IR /etc/selinux/config . .sp .BR selinux_path () returns the top-level SELinux configuration directory. .sp .BR selinux_policy_root () returns the top-level policy directory. .sp .BR selinux_binary_policy_path () returns the binary policy file loaded into kernel. .sp .BR selinux_current_policy_path () returns the currently loaded policy file from the kernel. .sp .BR selinux_default_type_path () returns the context file mapping roles to default types. .sp .BR selinux_failsafe_context_path () returns the failsafe context for emergency logins. .sp .BR selinux_removable_context_path () returns the filesystem context for removable media. .sp .BR selinux_default_context_path () returns the system-wide default contexts for user sessions. .sp .BR selinux_user_contexts_path () returns the directory containing per-user default contexts. .sp .BR selinux_usersconf_path () returns the file containing mapping between Linux Users and SELinux users. .sp .BR selinux_x_context_path () returns the file containing configuration for XSELinux extension. .sp .BR selinux_sepgsql_context_path () returns the file containing configuration for SE-PostgreSQL. .sp .BR selinux_netfilter_context_path () returns the default netfilter context. .sp .BR selinux_file_context_path () returns the default system file contexts configuration. .sp .BR selinux_file_context_local_path () returns the local customization file contexts configuration. .sp .BR selinux_file_context_homedir_path () returns the home directory file contexts configuration. .sp .BR selinux_media_context_path () returns the file contexts for media device nodes. .sp .BR selinux_contexts_path () returns the directory containing all of the context configuration files. .sp .BR selinux_securetty_types_path () returns the defines tty types for newrole securettys. .sp .BR selinux_booleans_path () returns the initial policy boolean settings. . .SH AUTHOR This manual page was written by Dan Walsh . . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_boolean_sub.30100644 0000000 0000000 00000001533 13756670063 017536 0ustar000000000 0000000 .TH "selinux_boolean_sub" "3" "11 June 2012" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" selinux_boolean_sub \- Search the translated name for a boolean_name record . .SH "SYNOPSIS" .B #include .sp .BI "char *selinux_boolean_sub(const char *" boolean_name ");" .sp .SH "DESCRIPTION" .BR selinux_boolean_sub () searches the .I \%/etc/selinux/{POLICYTYPE}/booleans.subs_dist file for a matching boolean_name record. If the record exists the boolean substitution name is returned. If not .BR \%selinux_boolean_sub () returns the original .IR \%boolean_name . .SH "RETURN VALUE" .BR selinux_boolean_sub () returns the .I boolean_name or the substituted name on success. The returned value must be freed with .BR free "(3)." .BR selinux_boolean_sub () returns NULL on error. .SH "SEE ALSO" .BR security_get_boolean_names (3) libselinux/man/man3/selinux_booleans_path.30100644 0000000 0000000 00000000046 13756670063 020062 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_check_access.30100644 0000000 0000000 00000000037 13756670063 017642 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/selinux_check_passwd_access.30100644 0000000 0000000 00000000037 13756670063 021223 0ustar000000000 0000000 .so man3/security_compute_av.3 libselinux/man/man3/selinux_check_securetty_context.30100644 0000000 0000000 00000001004 13756670063 022167 0ustar000000000 0000000 .TH "selinux_check_securetty_context" "3" "1 January 2007" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" selinux_check_securetty_context \- check whether a SELinux tty security context is defined as a securetty context . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_check_securetty_context(char *" tty_context ); . .SH "DESCRIPTION" .BR selinux_check_securetty_context () returns 0 if tty_context is a securetty context, returns < 0 otherwise. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_colors_path.30100644 0000000 0000000 00000002123 13756670063 017557 0ustar000000000 0000000 .TH "selinux_colors_path" "3" "08 April 2011" "SELinux API documentation" .SH "NAME" selinux_colors_path \- Return a path to the active SELinux policy color configuration file . .SH "SYNOPSIS" .B #include .sp .B const char *selinux_colors_path(void); . .SH "DESCRIPTION" .BR selinux_colors_path () returns the path to the active policy color configuration file. .sp The path is built from the path returned by .BR selinux_policy_root "(3)" with .I /secolor.conf appended. .sp This optional configuration file whose format is shown in .BR \%secolor.conf (5), controls the colors to be associated with the .I raw context components of the .BR selinux_raw_context_to_color "(3)" function when information is to be displayed by an SELinux color-aware application. . .SH "RETURN VALUE" On success, the path to the active policy color configuration file is returned. If a path is not available NULL is returned. . .SH "ERRORS" None. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_policy_root "(3), " selinux_config "(5), " selinux_raw_context_to_color "(3), " secolor.conf "(5)" libselinux/man/man3/selinux_contexts_path.30100644 0000000 0000000 00000000046 13756670063 020127 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_current_policy_path.30100644 0000000 0000000 00000000046 13756670063 021321 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_default_context_path.30100644 0000000 0000000 00000000046 13756670063 021450 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_default_type_path.30100644 0000000 0000000 00000000046 13756670063 020745 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_failsafe_context_path.30100644 0000000 0000000 00000000046 13756670063 021576 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_file_context_cmp.30100644 0000000 0000000 00000002272 13756670063 020571 0ustar000000000 0000000 .TH "selinux_file_context_cmp" "3" "08 March 2011" "SELinux API documentation" .SH "NAME" selinux_file_context_cmp \- Compare two SELinux security contexts excluding the 'user' component . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_file_context_cmp(const char *" a ", " .RS .BI "const char *" b ");" .RE . .SH "DESCRIPTION" .BR selinux_file_context_cmp () compares two context strings excluding the user component with .BR strcmp (3) as shown in the .B EXAMPLE section. .sp This is useful as for most object contexts, the user component is not relevant. . .SH "RETURN VALUE" The return values follow the .BR strcmp (3) function, where: .RS 0 if they are equal. .RE .RS 1 if .I a is greater than .I b .RE .RS \-1 if .I a is less than .I b .RE . .SH "ERRORS" None. . .SH "NOTES" The contexts being compared do not specifically need to be file contexts. . .SH "EXAMPLE" If context .I a is: .RS user_u:user_r:user_t:s0 .RE .sp and context .I b is: .RS root:user_r:user_t:s0 .RE .sp then the actual strings compared are: .RS :user_r:user_t:s0 and :user_r:user_t:s0 .RE .sp Therefore they will match and .BR selinux_file_context_cmp () will return zero. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_file_context_homedir_path.30100644 0000000 0000000 00000000046 13756670063 022452 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_file_context_local_path.30100644 0000000 0000000 00000000046 13756670063 022115 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_file_context_path.30100644 0000000 0000000 00000000046 13756670063 020743 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_file_context_verify.30100644 0000000 0000000 00000004721 13756670063 021317 0ustar000000000 0000000 .TH "selinux_file_context_verify" "3" "08 March 2011" "SELinux API documentation" .SH "NAME" selinux_file_context_verify \- Compare the SELinux security context on disk to the default security context required by the policy file contexts file . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_file_context_verify(const char *" path ", mode_t " mode ");" . .SH "DESCRIPTION" .BR selinux_file_context_verify () compares the context of the specified .I path that is held on disk (in the extended attribute), to the system default entry held in the file contexts series of files. .sp The .I mode may be zero. .sp Note that the two contexts are compared for "significant" differences (i.e. the user component of the contexts are ignored) as shown in the .B EXAMPLE section. . .SH "RETURN VALUE" If the contexts significantly match, 1 (one) is returned. .sp If the contexts do not match 0 (zero) is returned and .I errno is set to either .B ENOENT or .B EINVAL for the reasons listed in the .B ERRORS section, or if .I errno = 0 then the contexts did not match. .sp On failure \-1 is returned and .I errno set appropriately. . .SH "ERRORS" .TP .B ENOTSUP if extended attributes are not supported by the file system. .TP .B ENOENT if there is no entry in the file contexts series of files or .I path does not exist. .TP .B EINVAL if the entry in the file contexts series of files or .I path are invalid, or the returned context fails validation. .TP .B ENOMEM if attempt to allocate memory failed. . .SH "FILES" The following configuration files (the file contexts series of files) supporting the active policy will be used (should they exist) to determine the .I path default context: .sp .RS .I contexts/files/file_contexts - This file must exist. .sp .I contexts/files/file_contexts.local - If exists has local customizations. .sp .I contexts/files/file_contexts.homedirs - If exists has users home directory customizations. .sp .I contexts/files/file_contexts.subs - If exists has substitutions that are then applied to the 'in memory' version of the file contexts files. .RE . .SH "EXAMPLE" If the files context is: .RS unconfined_u:object_r:admin_home_t:s0 .RE .sp and the default context defined in the file contexts file is: .RS system_u:object_r:admin_home_t:s0 .RE .sp then the actual strings compared are: .RS :object_r:admin_home_t:s0 and :object_r:admin_home_t:s0 .RE .sp Therefore they will match and .BR selinux_file_context_verify () will return 1. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_getenforcemode.30100644 0000000 0000000 00000001400 13756670063 020225 0ustar000000000 0000000 .TH "selinux_getenforcemode" "3" "25 May 2004" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" selinux_getenforcemode \- get the enforcing state of SELinux . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_getenforcemode(int *" enforce ); . .SH "DESCRIPTION" .BR selinux_getenforcemode () Reads the contents of the .I /etc/selinux/config file to determine how the system was setup to run SELinux. Sets the value of .I enforce to 1 if SELinux should be run in enforcing mode. Sets the value of .I enforce to 0 if SELinux should be run in permissive mode. Sets the value of .I enforce to \-1 if SELinux should be disabled. . .SH "RETURN VALUE" On success, zero is returned. On failure, \-1 is returned. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_getpolicytype.30100644 0000000 0000000 00000001176 13756670063 020152 0ustar000000000 0000000 .TH "selinux_getpolicytype" "3" "24 Sep 2008" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" selinux_getpolicytype \- get the type of SELinux policy running on the system . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_getpolicytype(char **" policytype ); . .SH "DESCRIPTION" .BR selinux_getpolicytype () Reads the contents of the .I /etc/selinux/config file to determine the SELinux policy used on the system, and sets .I \%policytype accordingly. Free .I \%policytype with .BR free (3). . .SH "RETURN VALUE" On success, zero is returned. On failure, \-1 is returned. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_homedir_context_path.30100644 0000000 0000000 00000000046 13756670063 021453 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_init_load_policy.30100644 0000000 0000000 00000000040 13756670063 020557 0ustar000000000 0000000 .so man3/security_load_policy.3 libselinux/man/man3/selinux_lsetfilecon_default.30100644 0000000 0000000 00000001226 13756670063 021260 0ustar000000000 0000000 .TH "selinux_lsetfilecon_default" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" .SH "NAME" selinux_lsetfilecon_default \- set the file context to the system defaults . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_lsetfilecon_default(const char *" path ");" . .SH "DESCRIPTION" .BR selinux_lsetfilecon_default () sets the file context to the system defaults. . .SH "RETURN VALUE" Returns zero on success or \-1 otherwise. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_file_context_cmp "(3), " selinux_file_context_verify "(3), " matchpathcon "(3), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/selinux_media_context_path.30100644 0000000 0000000 00000000046 13756670063 021103 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_mkload_policy.30100644 0000000 0000000 00000000040 13756670063 020064 0ustar000000000 0000000 .so man3/security_load_policy.3 libselinux/man/man3/selinux_netfilter_context_path.30100644 0000000 0000000 00000000046 13756670063 022020 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_path.30100644 0000000 0000000 00000000046 13756670063 016200 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_policy_root.30100644 0000000 0000000 00000002055 13756670063 017610 0ustar000000000 0000000 .TH "selinux_policy_root" "3" "25 May 2004" "dwalsh@redhat.com" "SELinux API documentation" .SH "NAME" selinux_policy_root \- return the path of the SELinux policy files for this machine selinux_set_policy_root \- Set an alternate SELinux root path for the SELinux policy files for this machine. . .SH "SYNOPSIS" .B #include .sp .B const char *selinux_policy_root(void); . .sp .B int selinux_set_policy_root(const char *policypath); . .SH "DESCRIPTION" .BR selinux_policy_root () reads the contents of the .I /etc/selinux/config file to determine which policy files should be used for this machine. . .BR selinux_set_policy_root () sets up all policy paths based on the alternate root .I /etc/selinux/config file to determine which policy files should be used for this machine. . .SH "RETURN VALUE" On success, selinux_policy_root returns a directory path containing the SELinux policy files. On failure, selinux_policy_root returns NULL. On success, selinux_set_policy_root returns 0 on success -1 on failure. . .SH "SEE ALSO" .BR selinux "(8)" libselinux/man/man3/selinux_raw_context_to_color.30100644 0000000 0000000 00000006176 13756670063 021513 0ustar000000000 0000000 .TH "selinux_raw_context_to_color" "3" "08 April 2011" "SELinux API documentation" .SH "NAME" selinux_raw_context_to_color \- Return RGB color string for an SELinux security context . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_raw_context_to_color(char *" raw ", " .RS .BI "char **" color_str ");" .RE . .SH "DESCRIPTION" .BR selinux_raw_context_to_color () returns a .I color_str associated to the raw context .I raw provided that the .BR mcstransd "(8)" daemon is running, the policy is an MLS type policy (MCS or MLS) and there is a color configuration file .BR \%secolor.conf (5) (see the .B FILES section). .sp The .I color_str string is a space separated list of eight hexadecimal RGB triples, each prefixed by a hash character (#). These represent the user:role:type:range components of the foreground and background colors. An example string is shown in the .B EXAMPLE section. The returned .I color_str string must be freed with .BR free "(3)." If a color has not been configured for a specific user, role, type and/or range component of context .IR raw "," then .BR \%selinux_raw_context_to_color () will select the color returned in .I color_str in order of precedence as follows: .RS role, type, range .br user, type, range .br user, role, range .br user, role, type .br .RE If there are no entries in the .BR secolor.conf (5) file for any of the components of context .I raw (or the file is not present), then the default string returned in .I color_str is: .sp .RS ----- user ---- ---- role ---- ---- type ---- ---- range ---- .br #000000 #ffffff #000000 #ffffff #000000 #ffffff #000000 #ffffff .sp .RE . .SH "RETURN VALUE" On success, zero is returned. .br On failure, \-1 is returned with .I errno set appropriately. . .SH "ERRORS" .B ENOENT If the .BR mcstransd "(8)" daemon is not running. . .SH "FILES" .BR selinux_raw_context_to_color () obtains the translated entry from the active policy .BR secolor.conf "(5)" file as returned by .BR \%selinux_colors_path (3). The file format is described in .BR \%secolor.conf (5). . .SH "NOTES" 1. The primary use of .BR selinux_raw_context_to_color () is to return a color that corresponds to a range, that can then be used to highlight information at different MLS levels. .sp 2. The .BR mcstransd "(8)" daemon process security level must dominate the .I raw security level passed to it by the .BR selinux_raw_context_to_color () function. If not, the range color selected will be as defined by the order of precedence. . .SH "EXAMPLE" .BR selinux_raw_context_to_color () returns the foreground and background colors of the context string components (user:role:type:range) as RGB triples as follows: .sp user : role : type : range .br fg bg : fg bg : fg bg : fg bg .br #000000 #ffffff #ffffff #000000 #d2b48c #ffa500 #000000 #008000 .br black white : white black : tan orange : black green .br . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_colors_path "(3), " mcstransd "(8), " secolor.conf "(5), " selinux_raw_to_trans_context "(3), " selinux_trans_to_raw_context "(3), " free "(3)" libselinux/man/man3/selinux_removable_context_path.30100644 0000000 0000000 00000000046 13756670063 022000 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_restorecon.30100644 0000000 0000000 00000015540 13756670063 017434 0ustar000000000 0000000 .TH "selinux_restorecon" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selinux_restorecon \- restore file(s) default SELinux security contexts . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_restorecon(const char *" pathname , .in +\w'int selinux_restorecon('u .br .BI "unsigned int " restorecon_flags ");" .in . .SH "DESCRIPTION" .BR selinux_restorecon () restores file default security contexts on filesystems that support extended attributes (see .BR xattr (7)), based on: .sp .RS .IR pathname containing a directory or file to be relabeled. .br If this is a directory and the .IR restorecon_flags .B SELINUX_RESTORECON_RECURSE has been set (for descending through directories), then .BR selinux_restorecon () will write an SHA1 digest of the combined specfiles (see the .B NOTES section for details) to an extended attribute of .IR security.restorecon_last once the relabeling has been completed successfully. This digest will be checked should .BR selinux_restorecon () be rerun with the .IR restorecon_flags .B SELINUX_RESTORECON_RECURSE flag set. If any of the specfiles had been updated, the digest will also be updated. However if the digest is the same, no relabeling checks will take place (unless the .B SELINUX_RESTORECON_IGNORE_DIGEST flag is set). .sp .IR restorecon_flags contains the labeling option/rules as follows: .sp .RS .sp .B SELINUX_RESTORECON_IGNORE_DIGEST force the checking of labels even if the stored SHA1 digest matches the specfiles SHA1 digest. The specfiles digest will be written to the .IR security.restorecon_last extended attribute once relabeling has been completed successfully provided the .B SELINUX_RESTORECON_NOCHANGE flag has not been set. .sp .B SELINUX_RESTORECON_NOCHANGE don't change any file labels (passive check) or update the digest in the .IR security.restorecon_last extended attribute. .sp .B SELINUX_RESTORECON_SET_SPECFILE_CTX If set, reset the files label to match the default specfile context. If not set only reset the files "type" component of the context to match the default specfile context. .sp .B SELINUX_RESTORECON_RECURSE change file and directory labels recursively (descend directories) and if successful write an SHA1 digest of the combined specfiles to an extended attribute as described in the .B NOTES section. .sp .B SELINUX_RESTORECON_VERBOSE log file label changes. .RS Note that if .B SELINUX_RESTORECON_VERBOSE and .B SELINUX_RESTORECON_PROGRESS flags are set, then .B SELINUX_RESTORECON_PROGRESS will take precedence. .RE .sp .B SELINUX_RESTORECON_PROGRESS show progress by outputting the number of files in 1k blocks processed to stdout. If the .B SELINUX_RESTORECON_MASS_RELABEL flag is also set then the approximate percentage complete will be shown. .sp .B SELINUX_RESTORECON_MASS_RELABEL generally set when relabeling the entire OS, that will then show the approximate percentage complete. The .B SELINUX_RESTORECON_PROGRESS flag must also be set. .sp .B SELINUX_RESTORECON_REALPATH convert passed-in .I pathname to the canonical pathname using .BR realpath (3). .sp .B SELINUX_RESTORECON_XDEV prevent descending into directories that have a different device number than the .I pathname entry from which the descent began. .sp .B SELINUX_RESTORECON_ADD_ASSOC attempt to add an association between an inode and a specification. If there is already an association for the inode and it conflicts with the specification, then use the last matching specification. .sp .B SELINUX_RESTORECON_ABORT_ON_ERROR abort on errors during the file tree walk. .sp .B SELINUX_RESTORECON_SYSLOG_CHANGES log any label changes to .BR syslog (3). .sp .B SELINUX_RESTORECON_LOG_MATCHES log what specfile context matched each file. .sp .B SELINUX_RESTORECON_IGNORE_NOENTRY ignore files that do not exist. .sp .B SELINUX_RESTORECON_IGNORE_MOUNTS do not read .B /proc/mounts to obtain a list of non-seclabel mounts to be excluded from relabeling checks. .br Setting .B SELINUX_RESTORECON_IGNORE_MOUNTS is useful where there is a non-seclabel fs mounted with a seclabel fs mounted on a directory below this. .RE .sp The behavior regarding the checking and updating of the SHA1 digest described above is the default behavior. It is possible to change this by first calling .BR selabel_open (3) and not enabling the .B SELABEL_OPT_DIGEST option, then calling .BR selinux_restorecon_set_sehandle (3) to set the handle to be used by .BR selinux_restorecon (3). .sp If the .I pathname is a directory path, then it is possible to set directories to be excluded from the path by calling .BR selinux_restorecon_set_exclude_list (3) with a .B NULL terminated list before calling .BR selinux_restorecon (3). .sp By default .BR selinux_restorecon (3) reads .B /proc/mounts to obtain a list of non-seclabel mounts to be excluded from relabeling checks unless the .B SELINUX_RESTORECON_IGNORE_MOUNTS flag has been set. .RE . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "NOTES" .IP "1." 4 To improve performance when relabeling file systems recursively (e.g. the .IR restorecon_flags .B SELINUX_RESTORECON_RECURSE flag is set) .BR selinux_restorecon () will write an SHA1 digest of the specfiles that are processed by .BR selabel_open (3) to an extended attribute named .IR security.restorecon_last to the directory specified in the .IR pathname . .IP "2." 4 To check the extended attribute entry use .BR getfattr (1) , for example: .sp .RS .RS getfattr -e hex -n security.restorecon_last / .RE .RE .IP "3." 4 The SHA1 digest is calculated by .BR selabel_open (3) concatenating the specfiles it reads during initialisation with the resulting digest and list of specfiles being retrieved by .BR selabel_digest (3). .IP "4." 4 The specfiles consist of the mandatory .I file_contexts file plus any subs, subs_dist, local and homedir entries (text or binary versions) as determined by any .BR selabel_open (3) options e.g. .BR SELABEL_OPT_BASEONLY . .sp Should any of the specfiles have changed, then when .BR selinux_restorecon () is run again with the .B SELINUX_RESTORECON_RECURSE flag set, a new SHA1 digest will be calculated and all files will be automatically relabeled depending on the settings of the .B SELINUX_RESTORECON_SET_SPECFILE_CTX flag (provided .B SELINUX_RESTORECON_NOCHANGE is not set). .IP "5." 4 .B /sys and in-memory filesystems do not support the .IR security.restorecon_last extended attribute and are automatically excluded from any relabeling checks. .IP "6." 4 By default .B stderr is used to log output messages and errors. This may be changed by calling .BR selinux_set_callback (3) with the .B SELINUX_CB_LOG .I type option. . .SH "SEE ALSO" .BR selinux_restorecon_set_sehandle (3), .br .BR selinux_restorecon_default_handle (3), .br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_set_alt_rootpath (3), .br .BR selinux_restorecon_xattr (3), .br .BR selinux_set_callback (3) libselinux/man/man3/selinux_restorecon_default_handle.30100644 0000000 0000000 00000003137 13756670063 022452 0ustar000000000 0000000 .TH "selinux_restorecon_default_handle" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selinux_restorecon_default_handle \- sets default parameters for .BR selinux_restorecon (3) . .SH "SYNOPSIS" .B #include .br .B #include .sp .B "struct selabel_handle *selinux_restorecon_default_handle(void);" . .SH "DESCRIPTION" .BR selinux_restorecon_default_handle () sets default parameters for .BR selinux_restorecon (3) by calling .BR selabel_open (3) with the .B SELABEL_OPT_DIGEST option only. This will enable a digest to be calculated on the currently loaded policy .BR file_contexts (5) set of files as described in the .B NOTES section of .BR selinux_restorecon (3). .sp Calling .BR selinux_restorecon_default_handle () is optional, however if used then .BR selinux_restorecon_set_sehandle (3) should be called with the returned handle to set this for use by .BR selinux_restorecon (3). .sp .BR selinux_restorecon_default_handle () is optional as .BR selinux_restorecon (3) will automatically call this and .BR selinux_restorecon_set_sehandle (3) provided a handle has not already been set, for example by .BR selinux_restorecon_set_sehandle (3) to set customised .BR selabel_open (3) parameters. . .SH "RETURN VALUE" A non\-NULL handle value is returned on success. On error, NULL is returned and .I errno is set appropriately. . .SH "SEE ALSO" .BR selinux_restorecon (3), .br .BR selinux_restorecon_set_sehandle (3), .br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_set_alt_rootpath (3), .br .BR selinux_restorecon_xattr (3) libselinux/man/man3/selinux_restorecon_set_alt_rootpath.30100644 0000000 0000000 00000001716 13756670063 023067 0ustar000000000 0000000 .TH "selinux_restorecon_set_alt_rootpath" "3" "29 May 2016" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selinux_restorecon_set_alt_rootpath \- set an alternate rootpath. . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_restorecon_set_alt_rootpath(const char *" alt_rootpath ");" .in +\w'void selinux_restorecon_set_alt_rootpath('u . .SH "DESCRIPTION" .BR selinux_restorecon_set_alt_rootpath () passes to .BR selinux_restorecon (3) a pointer containing an alternate rootpath .IR alt_rootpath . .sp .BR selinux_restorecon_set_alt_rootpath () must be called prior to .BR selinux_restorecon (3). . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. . .SH "SEE ALSO" .BR selinux_restorecon (3), .br .BR selinux_restorecon_set_sehandle (3), .br .BR selinux_restorecon_default_handle (3), .br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_xattr (3) libselinux/man/man3/selinux_restorecon_set_exclude_list.30100644 0000000 0000000 00000001673 13756670063 023055 0ustar000000000 0000000 .TH "selinux_restorecon_set_exclude_list" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selinux_restorecon_set_exclude_list \- set list of directories to be excluded from relabeling. . .SH "SYNOPSIS" .B #include .sp .BI "void selinux_restorecon_set_exclude_list(const char **" exclude_list ");" .in +\w'void selinux_restorecon_set_exclude_list('u . .SH "DESCRIPTION" .BR selinux_restorecon_set_exclude_list () passes to .BR selinux_restorecon (3) a pointer containing a .B NULL terminated list of one or more directories that are not to be relabeled in .IR exclude_list . .sp .BR selinux_restorecon_set_exclude_list () must be called prior to .BR selinux_restorecon (3). . .SH "SEE ALSO" .BR selinux_restorecon (3), .br .BR selinux_restorecon_set_sehandle (3), .br .BR selinux_restorecon_default_handle (3), .br .BR selinux_restorecon_set_alt_rootpath (3), .br .BR selinux_restorecon_xattr (3) libselinux/man/man3/selinux_restorecon_set_sehandle.30100644 0000000 0000000 00000001736 13756670063 022154 0ustar000000000 0000000 .TH "selinux_restorecon_set_sehandle" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selinux_restorecon_set_sehandle \- set a labeling handle for use by .BR selinux_restorecon (3) . .SH "SYNOPSIS" .B #include .br .B #include .sp .BI "void selinux_restorecon_set_sehandle(struct selabel_handle *" handle ");" .in +\w'void selinux_restorecon_set_sehandle('u . .SH "DESCRIPTION" .BR selinux_restorecon_set_sehandle () sets the .I handle to be use by .BR selinux_restorecon (3) when relabeling files. .sp .BR selinux_restorecon_set_sehandle () is generally used when customised .BR selabel_open (3) parameters are required to perform relabeling operations with .BR selinux_restorecon (3). . .SH "SEE ALSO" .BR selinux_restorecon (3), .br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_default_handle (3), .br .BR selinux_restorecon_set_alt_rootpath (3), .br .BR selinux_restorecon_xattr (3) libselinux/man/man3/selinux_restorecon_xattr.30100644 0000000 0000000 00000007032 13756670063 020653 0ustar000000000 0000000 .TH "selinux_restorecon_xattr" "3" "30 July 2016" "" "SELinux API documentation" .SH "NAME" selinux_restorecon_xattr \- manage default .I security.restorecon_last extended attribute entries added by .BR selinux_restorecon (3), .BR setfiles (8) or .BR restorecon (8). .SH "SYNOPSIS" .B #include .sp .BI "int selinux_restorecon_xattr(const char *" pathname , .in +\w'int selinux_restorecon('u .br .BI "unsigned int " xattr_flags , .br .BI "struct dir_xattr ***" xattr_list ");" .in . .SH "DESCRIPTION" .BR selinux_restorecon_xattr () returns a linked list of .B dir_xattr structures containing information described below based on: .sp .RS .IR pathname containing a directory tree to be searched for .I security.restorecon_last extended attribute entries. .sp .IR xattr_flags contains options as follows: .sp .RS .sp .B SELINUX_RESTORECON_XATTR_RECURSE recursively descend directories. .sp .B SELINUX_RESTORECON_XATTR_DELETE_NONMATCH_DIGESTS delete non-matching digests from each directory in .IR pathname . .sp .B SELINUX_RESTORECON_XATTR_DELETE_ALL_DIGESTS delete all digests from each directory in .IR pathname . .sp .B SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS do not read .B /proc/mounts to obtain a list of non-seclabel mounts to be excluded from the search. .br Setting .B SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS is useful where there is a non-seclabel fs mounted with a seclabel fs mounted on a directory below this. .RE .sp .I xattr_list is the returned pointer to a linked list of .B dir_xattr structures, each containing the following information: .sp .RS .ta 4n 16n 24n .nf struct dir_xattr { char *directory; char *digest; /* Printable hex encoded string */ enum digest_result result; struct dir_xattr *next; }; .fi .ta .RE .sp The .B result entry is enumerated as follows: .RS .ta 4n 16n 24n .nf enum digest_result { MATCH = 0, NOMATCH, DELETED_MATCH, DELETED_NOMATCH, ERROR }; .fi .ta .RE .sp .I xattr_list must be set to .B NULL before calling .BR selinux_restorecon_xattr (3). The caller is responsible for freeing the returned .I xattr_list entries in the linked list. .RE .sp See the .B NOTES section for more information. .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and .I errno is set appropriately. .SH "NOTES" .IP "1." 4 By default .BR selinux_restorecon_xattr (3) will use the default set of specfiles described in .BR files_contexts (5) to calculate the initial SHA1 digest to be used for comparison. To change this default behavior .BR selabel_open (3) must be called specifying the required .B SELABEL_OPT_PATH and setting the .B SELABEL_OPT_DIGEST option to a non-NULL value. .BR selinux_restorecon_set_sehandle (3) is then called to set the handle to be used by .BR selinux_restorecon_xattr (3). .IP "2." 4 By default .BR selinux_restorecon_xattr (3) reads .B /proc/mounts to obtain a list of non-seclabel mounts to be excluded from searches unless the .B SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS flag has been set. .IP "3." 4 .B RAMFS and .B TMPFS filesystems do not support the .IR security.restorecon_last extended attribute and are automatically excluded from searches. .IP "4." 4 By default .B stderr is used to log output messages and errors. This may be changed by calling .BR selinux_set_callback (3) with the .B SELINUX_CB_LOG .I type option. .SH "SEE ALSO" .BR selinux_restorecon (3) .br .BR selinux_restorecon_set_sehandle (3), .br .BR selinux_restorecon_default_handle (3), .br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_set_alt_rootpath (3), .br .BR selinux_set_callback (3) libselinux/man/man3/selinux_securetty_types_path.30100644 0000000 0000000 00000000046 13756670063 021533 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_set_callback.30100644 0000000 0000000 00000005147 13756670063 017662 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selinux_set_callback" "3" "20 Jun 2007" "" "SELinux API documentation" .SH "NAME" selinux_set_callback \- userspace SELinux callback facilities . .SH "SYNOPSIS" .B #include .sp .BI "void selinux_set_callback(int " type ", union selinux_callback " callback ");" . .SH "DESCRIPTION" .BR selinux_set_callback () sets the callback indicated by .I type to the value of .IR callback , which should be passed as a function pointer cast to type .B union .BR selinux_callback . All callback functions should return a negative value with .I errno set appropriately on error. The available values for .I type are: .TP .B SELINUX_CB_LOG .BI "int (*" func_log ") (int " type ", const char *" fmt ", ...);" This callback is used for logging and should process the .BR printf (3) style .I fmt string and arguments as appropriate. The .I type argument indicates the type of message and will be set to one of the following: .B SELINUX_ERROR .B SELINUX_WARNING .B SELINUX_INFO .B SELINUX_AVC . .TP .B SELINUX_CB_AUDIT .BI "int (*" func_audit ") (void *" auditdata ", security_class_t " cls , .in +\w'int (*func_audit) ('u .BI "char *" msgbuf ", size_t " msgbufsize ");" .in This callback is used for supplemental auditing in AVC messages. The .I auditdata and .I cls arguments are the values passed to .BR avc_has_perm (3). A human-readable interpretation should be printed to .I msgbuf using no more than .I msgbufsize characters. . .TP .B SELINUX_CB_VALIDATE .BI "int (*" func_validate ") (char **" ctx ");" This callback is used for context validation. The callback may optionally modify the input context by setting the target of the .I ctx pointer to a new context. In this case, the old value should be freed with .BR freecon (3). The value of .I errno should be set to .B EINVAL to indicate an invalid context. . .TP .B SELINUX_CB_SETENFORCE .BI "int (*" func_setenforce ") (int " enforcing ");" This callback is invoked when the system enforcing state changes. The .I enforcing argument indicates the new value and is set to .I 1 for enforcing mode, and .I 0 for permissive mode. . .TP .B SELINUX_CB_POLICYLOAD .BI "int (*" func_policyload ") (int " seqno ");" This callback is invoked when the system security policy is reloaded. The .I seqno argument is the current sequential number of the policy generation in the system. . .SH "RETURN VALUE" None. . .SH "ERRORS" None. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR selabel_open (3), .BR avc_init (3), .BR avc_netlink_open (3), .BR selinux (8) libselinux/man/man3/selinux_set_mapping.30100644 0000000 0000000 00000005131 13756670063 017552 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2008 .TH "selinux_set_mapping" "3" "12 Jun 2008" "" "SELinux API documentation" .SH "NAME" selinux_set_mapping \- establish dynamic object class and permission mapping . .SH "SYNOPSIS" .B #include .sp .nf struct security_class_mapping { const char *name; const char *perms[]; }; .fi .sp .BI "int selinux_set_mapping(struct security_class_mapping *" map ");" . .SH "DESCRIPTION" .BR selinux_set_mapping () establishes a mapping from a user-provided ordering of object classes and permissions to the numbers actually used by the loaded system policy. Use of this function is highly preferred over the generated constants in the libselinux header files, as this method allows the policy's class and permission values to change over time. After the mapping is established, all libselinux functions that operate on class and permission values take the user-provided numbers, which are determined as follows: The .I map argument consists of an array of .B security_class_mapping structures, which must be terminated by a structure having a NULL name field. Except for this last structure, the .I name field should refer to the string name of an object class, and the corresponding .I perms field should refer to an array of permission bit names terminated by a NULL string. The object classes named in the mapping and the bit indexes of each set of permission bits named in the mapping are numbered in order starting from 1. These numbers are the values that should be passed to subsequent libselinux calls. . .SH "RETURN VALUE" Zero is returned on success. On error, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" .TP .B EINVAL One of the class or permission names requested in the mapping is not present in the loaded policy. .TP .B ENOMEM An attempt to allocate memory failed. . .SH "EXAMPLE" .RS .ta 4n 10n .nf struct security_class_mapping map[] = { { "file", { "create", "unlink", "read", "write", NULL } }, { "socket", { "bind", NULL } }, { "process", { "signal", NULL } }, { NULL } }; if (selinux_set_mapping(map) < 0) exit(1); .fi .ta .RE In this example, after the call has succeeded, classes .BR file , .BR socket , and .B process will be identified by 1, 2 and 3, respectively. Permissions .IR create , .IR unlink , .IR read , and .I write (for the .B file class) will be identified by 1, 2, 4, and 8 respectively. Classes and permissions not listed in the mapping cannot be used. . .SH "AUTHOR" Eamon Walsh . .SH "SEE ALSO" .BR avc_open (8), .BR selinux (8) libselinux/man/man3/selinux_set_policy_root.30100644 0000000 0000000 00000000037 13756670063 020461 0ustar000000000 0000000 .so man3/selinux_policy_root.3 libselinux/man/man3/selinux_status_close.30100644 0000000 0000000 00000000037 13756670063 017754 0ustar000000000 0000000 .so man3/selinux_status_open.3 libselinux/man/man3/selinux_status_deny_unknown.30100644 0000000 0000000 00000000037 13756670063 021365 0ustar000000000 0000000 .so man3/selinux_status_open.3 libselinux/man/man3/selinux_status_getenforce.30100644 0000000 0000000 00000000037 13756670063 020770 0ustar000000000 0000000 .so man3/selinux_status_open.3 libselinux/man/man3/selinux_status_open.30100644 0000000 0000000 00000006775 13756670063 017627 0ustar000000000 0000000 .TH "selinux_status_open" "3" "22 January 2011" "kaigai@ak.jp.nec.com" "SELinux API documentation" .SH "NAME" selinux_status_open, selinux_status_close, selinux_status_updated, selinux_status_getenforce, selinux_status_policyload and selinux_status_deny_unknown \- reference the SELinux kernel status without invocation of system calls . .SH "SYNOPSIS" .B #include .sp .BI "int selinux_status_open(int " fallback ");" .sp .BI "void selinux_status_close(void);" .sp .BI "int selinux_status_updated(void);" .sp .BI "int selinux_status_getenforce(void);" .sp .BI "int selinux_status_policyload(void);" .sp .BI "int selinux_status_deny_unknown(void);" . .SH "DESCRIPTION" Linux 2.6.37 or later provides a SELinux kernel status page; being mostly placed on .I /sys/fs/selinux/status entry. It enables userspace applications to mmap this page with read-only mode, then it informs some status without system call invocations. .sp In some cases that a userspace application tries to apply heavy frequent access control; such as row-level security in databases, it will face unignorable cost to communicate with kernel space to check invalidation of userspace avc. .sp These functions provides applications a way to know some kernel events without system-call invocation or worker thread for monitoring. .sp .BR selinux_status_open () tries to .BR open (2) .I /sys/fs/selinux/status and .BR mmap (2) it in read-only mode. The file-descriptor and pointer to the page shall be stored internally; Don't touch them directly. Set 1 on the .I fallback argument to handle a case of older kernels without kernel status page support. In this case, this function tries to open a netlink socket using .BR avc_netlink_open (3) and overwrite corresponding callbacks ( setenforce and policyload). Thus, we need to pay attention to the interaction with these interfaces, when fallback mode is enabled. .sp .BR selinux_status_close () unmap the kernel status page and close its file descriptor, or close the netlink socket if fallbacked. .sp .BR selinux_status_updated () informs us whether something has been updated since the last call. It returns 0 if nothing was happened, however, 1 if something has been updated in this duration, or \-1 on error. .sp .BR selinux_status_getenforce () returns 0 if SELinux is running in permissive mode, 1 if enforcing mode, or \-1 on error. Same as .BR security_getenforce (3) except with or without system call invocation. .sp .BR selinux_status_policyload () returns times of policy reloaded on the running system, or \-1 on error. Note that it is not a reliable value on fallback-mode until it receive the first event message via netlink socket. Thus, don't use this value to know actual times of policy reloaded. .sp .BR selinux_status_deny_unknown () returns 0 if SELinux treats policy queries on undefined object classes or permissions as being allowed, 1 if such queries are denied, or \-1 on error. .sp Also note that these interfaces are not thread-safe, so you have to protect them from concurrent calls using exclusive locks when multiple threads are performing. . .SH "RETURN VALUE" .BR selinux_status_open () returns 0 or 1 on success. 1 means we are ready to use these interfaces, but netlink socket was opened as fallback instead of the kernel status page. On error, \-1 shall be returned. .sp Any other functions with a return value shall return its characteristic value as described above, or \-1 on errors. . .SH "SEE ALSO" .ad l .nh .BR mmap (2), .BR avc_netlink_open (3), .BR security_getenforce (3), .BR security_deny_unknown (3) libselinux/man/man3/selinux_status_policyload.30100644 0000000 0000000 00000000037 13756670063 021006 0ustar000000000 0000000 .so man3/selinux_status_open.3 libselinux/man/man3/selinux_status_updated.30100644 0000000 0000000 00000000037 13756670063 020275 0ustar000000000 0000000 .so man3/selinux_status_open.3 libselinux/man/man3/selinux_user_contexts_path.30100644 0000000 0000000 00000000046 13756670063 021165 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_usersconf_path.30100644 0000000 0000000 00000000046 13756670063 020267 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/selinux_x_context_path.30100644 0000000 0000000 00000000046 13756670063 020273 0ustar000000000 0000000 .so man3/selinux_binary_policy_path.3 libselinux/man/man3/set_matchpathcon_flags.30100644 0000000 0000000 00000004214 13756670063 020176 0ustar000000000 0000000 .TH "set_matchpathcon_flags" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" .SH "NAME" set_matchpathcon_flags, set_matchpathcon_invalidcon, set_matchpathcon_printf \- set flags controlling the operation of matchpathcon or matchpathcon_index and configure the behaviour of validity checking and error displaying . .SH "SYNOPSIS" .B #include .sp .BI "void set_matchpathcon_flags(unsigned int " flags ");" .sp .BI "void set_matchpathcon_invalidcon(int (*" f ")(const char *" path ", unsigned " lineno ", char *" context "));" .sp .BI "void set_matchpathcon_printf(void (*" f ")(const char *" fmt ", ...));" . .SH "DESCRIPTION" .BR set_matchpathcon_flags () sets the flags controlling the operation of .BR matchpathcon_init (3) and subsequently .BR matchpathcon_index (3) or .BR matchpathcon (3). If the .B MATCHPATHCON_BASEONLY flag is set, then only the base file contexts configuration file will be processed, not any dynamically generated entries or local customizations. .sp .BR set_matchpathcon_invalidcon () sets the function used by .BR matchpathcon_init (3) when checking the validity of a context in the file contexts configuration. If not set, then this defaults to a test based on .BR security_check_context (3), which checks validity against the active policy on a SELinux system. This can be set to instead perform checking based on a binary policy file, e.g. using .BR sepol_check_context (3), as is done by .B setfiles \-c. The function is also responsible for reporting any such error, and may include the .I path and .I lineno in such error messages. .sp .BR set_matchpathcon_printf () sets the function used by .BR matchpathcon_init (3) when displaying errors about the file contexts configuration. If not set, then this defaults to fprintf(stderr, fmt, ...). This can be set to redirect error reporting to a different destination. . .SH "RETURN VALUE" Returns zero on success or \-1 otherwise. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " matchpathcon "(3), " matchpathcon_index "(3), " set_matchpathcon_invalidcon "(3), " set_matchpathcon_printf "(3), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/set_matchpathcon_invalidcon.30100644 0000000 0000000 00000000042 13756670063 021223 0ustar000000000 0000000 .so man3/set_matchpathcon_flags.3 libselinux/man/man3/set_matchpathcon_printf.30100644 0000000 0000000 00000000042 13756670063 020377 0ustar000000000 0000000 .so man3/set_matchpathcon_flags.3 libselinux/man/man3/set_selinuxmnt.30100644 0000000 0000000 00000000033 13756670063 016552 0ustar000000000 0000000 .so man3/init_selinuxmnt.3 libselinux/man/man3/setcon.30100644 0000000 0000000 00000000022 13756670063 014762 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/setcon_raw.30100644 0000000 0000000 00000000022 13756670063 015633 0ustar000000000 0000000 .so man3/getcon.3 libselinux/man/man3/setexeccon.30100644 0000000 0000000 00000000026 13756670063 015633 0ustar000000000 0000000 .so man3/getexeccon.3 libselinux/man/man3/setexeccon_raw.30100644 0000000 0000000 00000000026 13756670063 016504 0ustar000000000 0000000 .so man3/getexeccon.3 libselinux/man/man3/setfilecon.30100644 0000000 0000000 00000003315 13756670063 015632 0ustar000000000 0000000 .TH "setfilecon" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation" .SH "NAME" setfilecon, fsetfilecon, lsetfilecon \- set SELinux security context of a file . .SH "SYNOPSIS" .B #include .sp .BI "int setfilecon(const char *" path ", char *" con ); .sp .BI "int setfilecon_raw(const char *" path ", char *" con ); .sp .BI "int lsetfilecon(const char *" path ", char *" con ); .sp .BI "int lsetfilecon_raw(const char *" path ", char *" con ); .sp .BI "int fsetfilecon(int "fd ", char *" con ); .sp .BI "int fsetfilecon_raw(int "fd ", char *" con ); . .SH "DESCRIPTION" .BR setfilecon () sets the security context of the file system object. .BR lsetfilecon () is identical to setfilecon, except in the case of a symbolic link, where the link itself has it's context set, not the file that it refers to. .BR fsetfilecon () is identical to setfilecon, only the open file pointed to by filedes (as returned by .BR open (2)) has it's context set in place of path. .BR setfilecon_raw (), .BR lsetfilecon_raw (), and .BR fsetfilecon_raw () behave identically to their non-raw counterparts but do not perform context translation. . .SH "RETURN VALUE" On success, zero is returned. On failure, \-1 is returned and .I errno is set appropriately. . .SH "ERRORS" If there is insufficient space remaining to store the extended attribute, .I errno is set to either .BR ENOSPC , or .B EDQUOT if quota enforcement was the cause. If extended attributes are not supported by the filesystem, or are disabled, .I errno is set to .BR ENOTSUP . The errors documented for the .BR stat (2) system call are also applicable here. . .SH "SEE ALSO" .BR selinux "(3), " freecon "(3), " getfilecon "(3), " setfscreatecon "(3)" libselinux/man/man3/setfilecon_raw.30100644 0000000 0000000 00000000026 13756670063 016477 0ustar000000000 0000000 .so man3/setfilecon.3 libselinux/man/man3/setfscreatecon.30100644 0000000 0000000 00000000032 13756670063 016500 0ustar000000000 0000000 .so man3/getfscreatecon.3 libselinux/man/man3/setfscreatecon_raw.30100644 0000000 0000000 00000000032 13756670063 017351 0ustar000000000 0000000 .so man3/getfscreatecon.3 libselinux/man/man3/setkeycreatecon.30100644 0000000 0000000 00000000033 13756670063 016661 0ustar000000000 0000000 .so man3/getkeycreatecon.3 libselinux/man/man3/setkeycreatecon_raw.30100644 0000000 0000000 00000000033 13756670063 017532 0ustar000000000 0000000 .so man3/getkeycreatecon.3 libselinux/man/man3/setsockcreatecon.30100644 0000000 0000000 00000000034 13756670063 017031 0ustar000000000 0000000 .so man3/getsockcreatecon.3 libselinux/man/man3/setsockcreatecon_raw.30100644 0000000 0000000 00000000034 13756670063 017702 0ustar000000000 0000000 .so man3/getsockcreatecon.3 libselinux/man/man3/sidget.30100644 0000000 0000000 00000000036 13756670063 014753 0ustar000000000 0000000 .so man3/avc_context_to_sid.3 libselinux/man/man3/sidput.30100644 0000000 0000000 00000000036 13756670063 015004 0ustar000000000 0000000 .so man3/avc_context_to_sid.3 libselinux/man/man3/string_to_av_perm.30100644 0000000 0000000 00000000044 13756670063 017214 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man3/string_to_security_class.30100644 0000000 0000000 00000000044 13756670063 020617 0ustar000000000 0000000 .so man3/security_class_to_string.3 libselinux/man/man5/0040755 0000000 0000000 00000000000 13756670063 013416 5ustar000000000 0000000 libselinux/man/man5/booleans.50100644 0000000 0000000 00000004571 13756670063 015312 0ustar000000000 0000000 .TH "booleans" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" booleans \- The SELinux booleans configuration files . .SH "DESCRIPTION" The \fIbooleans\fR file, if present contains booleans to support a specific distribution. .sp The \fIbooleans.local\fR file, if present contains locally generated booleans. .sp Both files contain a list of boolean names and their associated values. .sp Generally the \fIbooleans\fR and/or \fIbooleans.local\fR files are not present (they have been deprecated). However if there is an SELinux-aware application that uses the libselinux functions listed below, then these files may be present: .sp .RS .BR security_set_boolean_list "(3) " .RS Writes a \fIbooleans.local\fR file if flag \fIpermanent\fR = \fI1\fR. .sp .RE .RE .RS .BR security_load_booleans "(3) " .RS Looks for a \fIbooleans\fR and/or \fIbooleans.local\fR file at \fBselinux_booleans_path\fR(3) unless a specific path is specified as a parameter. .RE .RE .sp \fBbooleans\fR(8) has details on booleans and \fBsetsebool\fR(8) describes how booleans can now be set persistent across reboots. .sp \fBselinux_booleans_path\fR(3) will return the active policy path to these files. The default boolean files are: .RS .I /etc/selinux/{SELINUXTYPE}/booleans .br .I /etc/selinux/{SELINUXTYPE}/booleans.local .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" Both boolean files have the same format and contain one or more boolean names and their value. .sp The format is: .RS .I boolean_name .I value .sp .RE Where: .RS .I boolean_name .RS The name of the boolean. .RE .I value .RS The default setting for the boolean. This can be one of the following: .RS .IR true " | " false " | " 1 " | " 0 .RE .RE .RE .sp Note that if .B SETLOCALDEFS is set in the SELinux .I config file (see .BR selinux_config "(5)), then " selinux_mkload_policy "(3) will check for a " .I booleans.local file in the .BR selinux_booleans_path (3) and also a .I local.users file (see .BR local.users "(5)) in the " selinux_users_path "(3). " . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " booleans "(8), " setsebool "(8), " semanage "(8), " selinux_booleans_path "(3), " security_set_boolean_list "(3), " security_load_booleans "(3), " selinux_mkload_policy "(3), " selinux_users_path "(3), " selinux_config "(5), " local.users "(5) " libselinux/man/man5/customizable_types.50100644 0000000 0000000 00000003326 13756670063 017432 0ustar000000000 0000000 .TH "customizable_types" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" customizable_types \- The SELinux customizable types configuration file . .SH "DESCRIPTION" The \fIcustomizable_types\fR file contains a list of types that can be customised in some way by SELinux-aware applications. .sp Generally this is a file context type that is usually set on files that need to be shared among certain domains and where the administrator wants to manually manage the type. .sp The use of customizable types is deprecated as the preferred approach is to use .BR semanage (8) .BR fcontext (8) .BR ... (8). However, SELinux-aware applications such as .BR setfiles (8) will use this information to obtain a list of types relating to files that should not be relabeled. .sp .BR selinux_customizable_types_path (3) will return the active policy path to this file. The default customizable types file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/customizable_types .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp .BR is_context_customizable (3) reads this file to determine if a context is customisable or not for the active policy. . .SH "FILE FORMAT" Each line in the file consists of the following: .RS .I type .RE .sp Where: .RS .I type .RS The type defined in the policy that can be customised. .RE .RE . .SH "EXAMPLE" # ./contexts/customizable_types .br mount_loopback_t .br public_content_rw_t .br public_content_t .br swapfile_t .br sysadm_untrusted_content_t . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_customizable_types_path "(3), " is_context_customizable "(3), " semanage "(8), " setfiles "(8), " selinux_config "(5) " libselinux/man/man5/default_contexts.50100644 0000000 0000000 00000004674 13756670063 017067 0ustar000000000 0000000 .TH "default_contexts" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" default_contexts \- The SELinux default contexts configuration file . .SH "DESCRIPTION" The default contexts configuration file \fIdefault_contexts\fR contains entries that allow SELinux-aware login applications such as .BR PAM "(8) " .sp SELinux-aware login applications generally use one or more of the following libselinux functions that read these files from the active policy path: .RS .BR get_default_context "(3) " .br .BR get_ordered_context_list "(3) " .br .BR get_ordered_context_list_with_level "(3) " .br .BR get_default_context_with_level "(3) " .br .BR get_default_context_with_role "(3) " .br .BR get_default_context_with_rolelevel "(3) " .br .BR query_user_context "(3) " .br .BR manual_user_enter_context "(3) " .RE .sp The default context configuration file path for the active policy is returned by \fBselinux_default_contexts_path\fR(3). The default, default contexts file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/default_contexts .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" Each line in the default configuration file consists of the following: .RS .I login_process user_login_process [user_login_process] ... .RE .sp Where: .RS .I login_process .RS This consists of a \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] entry that represents the login process context that are defined in the policy. .RE .I user_login_process .RS This consists of one or more \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] entries that represent the user login process context defined in the policy. .RE .RE . .SH "EXAMPLE" # ./contexts/default_contexts .br system_r:crond_t:s0 system_r:system_crond_t:s0 .br system_r:local_login_t:s0 user_r:user_t:s0 staff_r:staff_t:s0 .br system_r:remote_login_t:s0 user_r:user_t:s0 .br system_r:sshd_t:s0 user_r:user_t:s0 .br system_r:sulogin_t:s0 sysadm_r:sysadm_t:s0 .br system_r:xdm_t:s0 user_r:user_t:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_default_contexts_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " libselinux/man/man5/default_type.50100644 0000000 0000000 00000002251 13756670063 016166 0ustar000000000 0000000 .TH "default_type" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" default_type \- The SELinux default type configuration file . .SH "DESCRIPTION" The \fIdefault_type\fR file contains entries that allow SELinux-aware applications such as \fBnewrole\fR(1) to select a default type for a role if one is not supplied. .sp \fBselinux_default_type_path\fR(3) will return the active policy path to this file. The default, default type file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/default_type .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp \fBget_default_type\fR(3) reads this file to determine a type for the active policy. . .SH "FILE FORMAT" Each line within the \fIdefault_type\fR file is formatted with \fIrole\fB:\fItype\fR entries where: .RS .I role .RS The SELinux role. .RE .I type .RS The domain type that is returned for this role. .RE . .SH "EXAMPLE" # ./contexts/default_type .br auditadm_r:auditadm_t .br user_r:user_t . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " get_default_type "(3), " newrole "(1), " selinux_default_type_path "(3), " selinux_config "(5) " libselinux/man/man5/failsafe_context.50100644 0000000 0000000 00000003733 13756670063 017025 0ustar000000000 0000000 .TH "failsafe_context" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" failsafe_context \- The SELinux fail safe context configuration file . .SH "DESCRIPTION" The .I failsafe_context file allows SELinux-aware applications such as .BR PAM "(8) " to obtain a known valid login context for an administrator if no valid default entries can be found elsewhere. .sp .BR selinux_failsafe_context_path "(3) " will return the active policy path to this file. The default failsafe context file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/failsafe_context .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp The following functions read this file from the active policy path if they cannot obtain a default context: .br .RS .BR get_default_context "(3) " .br .BR get_ordered_context_list "(3) " .br .BR get_ordered_context_list_with_level "(3) " .br .BR get_default_context_with_level "(3) " .br .BR get_default_context_with_role "(3) " .br .BR get_default_context_with_rolelevel "(3) " .br .BR query_user_context "(3) " .br .BR manual_user_enter_context "(3) " .RE . .SH "FILE FORMAT" The file consists of a single line entry as follows: .RS \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] .RE .sp Where: .RS .I role .I type .I range .RS A role, type and optional range (for MCS/MLS), separated by colons (:) to form a valid login process context for an administrator to access the system. .RE .RE . .SH "EXAMPLE" # ./contexts/failsafe_context .br unconfined_r:unconfined_t:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_failsafe_context_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " libselinux/man/man5/file_contexts.50100644 0000000 0000000 00000000030 13756670063 016340 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/man5/file_contexts.homedirs.50100644 0000000 0000000 00000000030 13756670063 020151 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/man5/file_contexts.local.50100644 0000000 0000000 00000000030 13756670063 017431 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/man5/file_contexts.subs.50100644 0000000 0000000 00000000030 13756670063 017313 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/man5/file_contexts.subs_dist.50100644 0000000 0000000 00000000030 13756670063 020336 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/man5/local.users.50100644 0000000 0000000 00000004011 13756670063 015727 0ustar000000000 0000000 .TH "local.users" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" local.users \- The SELinux local users configuration file . .SH "DESCRIPTION" The file contains local user definitions in the form of policy language user statements and is only found on older SELinux systems as it has been deprecated and replaced by the \fBsemange\fR(8) services. .sp This file is only read by \fBselinux_mkload_policy\fR(3) when \fBSETLOCALDEFS\fR in the SELinux \fIconfig\fR file (see \fBselinux_config\fR(5)) is set to \fI1\fR. .sp .BR selinux_users_path "(3) " will return the active policy path to the directory where this file is located. The default local users file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/users/local.users .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" The file consists of one or more entries terminated with '\fB;\fR', each on a separate line as follows: .RS \fBuser \fIseuser_id \fBroles \fIrole_id\fR [[\fBlevel \fIlevel\fR] [\fBrange \fIrange\fR]]\fB;\fR .RE .sp Where: .RS .B user .RS The user keyword. .RE .I seuser_id .RS The SELinux user identifier. .RE .B roles .RS The roles keyword. .RE .I role_id .RS One or more previously declared role identifiers. Multiple role identifiers consist of a space separated list enclosed in braces '{}'. .RE .B level .RS If MLS/MCS is configured, the level keyword. .RE .I level .RS The users default security level. Note that only the sensitivity component of the level (e.g. s0) is required. .RE .B range .RS If MLS/MCS is configured, the range keyword. .RE .I range .RS The current and clearance levels that the user can run. These are separated by a hyphen '\fB-\fR' as shown in the \fBEXAMPLE\fR section. .RE .RE . .SH "EXAMPLE" # ./users/local.users .br user test_u roles staff_r level s0 range s0 \- s15:c0.c1023; . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " semanage "(8), " selinux_users_path "(3), " selinux_config "(5), " selinux_mkload_policy "(3) " libselinux/man/man5/media.50100644 0000000 0000000 00000000031 13756670063 014552 0ustar000000000 0000000 .so man5/selabel_media.5 libselinux/man/man5/removable_context.50100644 0000000 0000000 00000002071 13756670063 017221 0ustar000000000 0000000 .TH "removable_context" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" removable_context \- The SELinux removable devices context configuration file . .SH "DESCRIPTION" This file contains the default label that should be used for removable devices. .sp .BR selinux_removable_context_path "(3) " will return the active policy path to this file. The default removable context file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/removable_context .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" The file consists of a single line entry as follows: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Where: .RS .I user role type range .RS A user, role, type and optional range (for MCS/MLS) separated by colons (:) that will be applied to removable devices. .RE .RE . .SH "EXAMPLE" # ./contexts/removable_contexts .br system_u:object_r:removable_t:s0 . .SH "SEE ALSO" .BR selinux "(8), " selinux_removable_context_path "(3), " selinux_config "(5) " libselinux/man/man5/secolor.conf.50100644 0000000 0000000 00000006311 13756670063 016074 0ustar000000000 0000000 .TH "secolor.conf" "5" "08 April 2011" "SELinux API documentation" .SH "NAME" secolor.conf \- The SELinux color configuration file . .SH "DESCRIPTION" This optional file controls the color to be associated to the context components associated to the .I raw context passed by .BR selinux_raw_context_to_color "(3)," when context related information is to be displayed in color by an SELinux-aware application. .sp .BR selinux_raw_context_to_color "(3)" obtains this color information from the active policy .B secolor.conf file as returned by .BR selinux_colors_path "(3)." . .SH "FILE FORMAT" The file format is as follows: .RS .B color .I color_name .BI "= #"color_mask .br [...] .sp .I context_component string .B = .I fg_color_name bg_color_name .br [...] .sp .RE Where: .br .B color .RS The color keyword. Each color entry is on a new line. .RE .I color_name .RS A single word name for the color (e.g. red). .RE .I color_mask .RS A color mask starting with a hash (#) that describes the hexadecimal RGB colors with black being #000000 and white being #ffffff. .RE .I context_component .RS The context component name that must be one of the following: .br .RS user, role, type or range .RE Each .IR context_component " " string " ..." entry is on a new line. .RE .I string .RS This is the .I context_component string that will be matched with the .I raw context component passed by .BR selinux_raw_context_to_color "(3)." .br A wildcard '*' may be used to match any undefined string for the user, role and type .I context_component entries only. .RE .I fg_color_name .RS The color_name string that will be used as the foreground color. A .I color_mask may also be used. .RE .I bg_color_name .RS The color_name string that will be used as the background color. A .I color_mask may also be used. .RE . .SH "EXAMPLES" Example 1 entries are: .RS color black = #000000 .br color green = #008000 .br color yellow = #ffff00 .br color blue = #0000ff .br color white = #ffffff .br color red = #ff0000 .br color orange = #ffa500 .br color tan = #D2B48C .sp user * = black white .br role * = white black .br type * = tan orange .br range s0\-s0:c0.c1023 = black green .br range s1\-s1:c0.c1023 = white green .br range s3\-s3:c0.c1023 = black tan .br range s5\-s5:c0.c1023 = white blue .br range s7\-s7:c0.c1023 = black red .br range s9\-s9:c0.c1023 = black orange .br range s15:c0.c1023 = black yellow .RE .sp Example 2 entries are: .RS color black = #000000 .br color green = #008000 .br color yellow = #ffff00 .br color blue = #0000ff .br color white = #ffffff .br color red = #ff0000 .br color orange = #ffa500 .br color tan = #d2b48c .sp user unconfined_u = #ff0000 green .br role unconfined_r = red #ffffff .br type unconfined_t = red orange .br user user_u = black green .br role user_r = white black .br type user_t = tan red .br user xguest_u = black yellow .br role xguest_r = black red .br type xguest_t = black green .br user sysadm_u = white black .br range s0:c0.c1023 = black white .br user * = black white .br role * = black white .br type * = black white .RE . .SH "SEE ALSO" .BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" libselinux/man/man5/securetty_types.50100644 0000000 0000000 00000002523 13756670063 016756 0ustar000000000 0000000 .TH "securetty_types" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" securetty_types \- The SELinux secure tty type configuration file . .SH "DESCRIPTION" The .I securetty_types file contains a list of types associated to secure tty type that are defined in the policy for use by SELinux-aware applications. .sp .BR selinux_securetty_types_path "(3) " will return the active policy path to this file. The default securetty types file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/securetty_types .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp .BR selinux_check_securetty_context "(3) reads this file to determine if a context is for a secure tty defined in the active policy. " .sp SELinux-aware applications such as .BR newrole "(1) use this information to check the status of a tty. " . .SH "FILE FORMAT" Each line in the file consists of the following entry: .sp .RS .I type .RS One or more type entries that are defined in the policy for secure tty devices. .RE .RE . .SH "EXAMPLE" # ./contexts/securetty_types .br sysadm_tty_device_t .br user_tty_device_t .br staff_tty_device_t . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_securetty_types_path "(3), " newrole "(1), " selinux_check_securetty_context "(3), " selinux_config "(5) " libselinux/man/man5/selabel_db.50100644 0000000 0000000 00000020376 13756670063 015565 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: KaiGai Kohei 2009 .TH "selabel_db" "5" "01 DEC 2011" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_db \- userspace SELinux labeling interface and configuration file format for the RDBMS objects context backend . .SH "SYNOPSIS" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" . .SH "DESCRIPTION" The DB contexts backend maps from a pair of object name and class into security contexts. It is used to find the appropriate context for database objects when relabeling a certain database. The returned \fIcontext\fR must be freed using \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) describes the function with its return and error codes. .sp The \fIobject_name\fR should be a fully qualified name using the hierarchy of database objects. For example, the \fBpg_class\fR table in the \fBpostgres\fR database and \fBpg_catalog\fR schema should be qualified as: .RS .B Bpostgres.pg_catalog.pg_class .RE .sp The \fBNOTES\fR section has further information on database support for namespace hierarchies. .sp The \fIobject_type\fR argument should be set to one of the following values: .RS .TP .B SELABEL_DB_DATABASE The .I object_name argument specifies the name of a database itself, such as "postgres". .TP .B SELABEL_DB_SCHEMA The .I object_name argument specifies the name of a schema object, such as "postgres.public". .TP .B SELABEL_DB_TABLE The .I object_name argument specifies the name of a table object, such as "postgres.public.my_table" .TP .B SELABEL_DB_COLUMN The .I object_name argument specifies the name of a column object, such as "postgres.public.my_table.user_id" .TP .B SELABEL_DB_TUPLE The .I object_name argument specifies the name of a table object which contains the tuples to be relabeled, such as "postgresql.public.my_table". Note that we have no way to identify individual tuple objects, except for WHERE clause on DML statements, because it has no name. .TP .B SELABEL_DB_PROCEDURE The .I object_name argument specifies the name of a procedure object, such as "postgres.public.my_func". Note that we don't support lookup of individual security contexts for procedures which have the same name but different arguments. .TP .B SELABEL_DB_SEQUENCE The .I object_name argument specifies the name of a sequence object, such as "postgres.public.my_seq". .TP .B SELABEL_DB_BLOB The .I object_name argument specifies the name of a large object, such as "postgres.16308". Note that a large object does not have a name, so it is identified by its identifier value. .TP .B SELABEL_DB_VIEW The .I object_name argument specifies the name of a view object, such as "postgres.public.my_view". .TP .B SELABEL_DB_LANGUAGE The .I object_name argument specifies the name of a language object, such as "postgres.public.tcl". .TP .B SELABEL_DB_EXCEPTION The .I object_name argument specifies the name of a exception object. .TP .B SELABEL_DB_DATATYPE The .I object_name argument specifies the name of a type or domain object, such as postgres.public.my_type. .RE .sp Any messages generated by \fBselabel_lookup\fR(3) are sent to \fIstderr\fR by default, although this can be changed by \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) behaves identically to \fBselabel_lookup\fR(3) but does not perform context translation. .sp The \fBFILES\fR section details the configuration files used to determine the database object context. . .SH "OPTIONS" In addition to the global options described in \fBselabel_open\fR(3), this backend recognizes the following options: .RS .TP .B SELABEL_OPT_PATH A non-null value for this option specifies a path to a file that will be opened in lieu of the standard DB contexts file. It tries to open the specfile designed for SE-PostgreSQL as default, so if another RDBMS uses this interface, it needs to give an explicit specfile designed for that RDBMS (see the \fBFILES\fR section for details). .RE . .SH "FILES" The database context file used to retrieve a context depends on the \fBSELABEL_OPT_PATH\fR parameter passed to \fBselabel_open\fR(3). If \fINULL\fR, then the \fBSELABEL_OPT_PATH\fR value will default to the active policy database contexts location (as returned by \fBselinux_sepgsql_context_path\fR(3)), otherwise the actual \fBSELABEL_OPT_PATH\fR value specified is used (this option must be used to support databases other than SE-PostgreSQL). .sp The default database object contexts file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/sepgsql_context .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp The entries within the database contexts file are shown in the \fBObject Name String Values\fR and \fBFILE FORMAT\fR sections. . .SH "Object Name String Values" The string name assigned to each \fIobject_type\fR argument that can be present in the database contexts file are: .TS center, allbox, tab(@); lI lB lB l . object_type@Text Name SELABEL_DB_DATABASE@db_database SELABEL_DB_SCHEMA@db_schema SELABEL_DB_VIEW@db_view SELABEL_DB_LANGUAGE@db_language SELABEL_DB_TABLE@db_table SELABEL_DB_COLUMN@db_column SELABEL_DB_TUPLE@db_tuple SELABEL_DB_PROCEDURE@db_procedure SELABEL_DB_SEQUENCE@db_sequence SELABEL_DB_BLOB@db_blob SELABEL_DB_EXCEPTION@db_exception SELABEL_DB_DATATYPE@db_datatype .TE . .SH "FILE FORMAT" Each line within the database contexts file is as follows: .RS .I object_type object_name context .RE .sp Where: .RS .I object_type .RS This is the string representation of the object type shown in the \fBObject Name String Values\fR section. .RE .I object_name .RS The key used to obtain the context based on the \fIobject_type\fR. .sp The entry can contain '*' for wildcard matching or '?' for substitution. .sp Note that if the '*' is used, then be aware that the order of entries in the file is important. The '*' on its own is used to ensure a default fallback context is assigned and should be the last entry in the \fIobject_type\fR block. .RE .I context .RS The security context that will be applied to the object. .RE .RE .sp The following example is for SE-PostgreSQL: .sp # ./contexts/sepgsql_contexts file .br # object_type object_name context .br db_database my_database system_u:object_r:sepgsql_db_t:s0 .br db_database * system_u:object_r:sepgsql_db_t:s0 .br db_schema *.* system_u:object_r:sepgsql_schema_t:s0 .br db_tuple row_low system_u:object_r:sepgsql_table_t:s0 .br db_tuple row_high system_u:object_r:sepgsql_table_t:s0:c1023 .br db_tuple *.*.* system_u:object_r:sepgsql_table_t:s0 . .SH "NOTES" .IP "1." 4 A suitable database contexts file needs to be written for the target RDBMS and the \fBSELABEL_OPT_PATH\fR option must be used in \fBselabel_open\fR(3) to load it. .IP "2." 4 The hierarchy of the namespace for database objects depends on the RDBMS, however the \fIselabel*\fR interfaces do not have any specific support for a namespace hierarchy. .sp SE-PostgreSQL has a namespace hierarchy where a database is the top level object with the schema being the next level. Under the schema object there can be other types of objects such as tables and procedures. This hierarchy is supported as follows: .RS .RS .sp If a security context is required for "my_table" table in the "public" schema within the "postgres" database, then the \fBselabel_lookup\fR(3) parameters for \fIobject_type\fR would be \fBSELABEL_DB_TABLE\fR and the \fIobject_name\fR would be "postgres.public.my_table", the security context (if available), would be returned in \fIcontext\fR. .RE .RE .IP "3." 4 If contexts are to be validated, then the global option \fBSELABEL_OPT_VALIDATE\fR must be set before calling \fBselabel_open\fR(3). If this is not set, then it is possible for an invalid context to be returned. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_sepgsql_context_path "(3), " freecon "(3), " selinux_config "(5) " libselinux/man/man5/selabel_file.50100644 0000000 0000000 00000022105 13756670063 016107 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_file" "5" "01 Dec 2011" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_file \- userspace SELinux labeling interface and configuration file format for the file contexts backend . .SH "SYNOPSIS" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" path ", int " mode ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" path ", int " mode ");" . .SH "DESCRIPTION" The file contexts backend maps from pathname/mode combinations into security contexts. It is used to find the appropriate context for each file when relabeling a file system. The returned \fIcontext\fR must be freed using \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) describes the function with its return and error codes, however the following \fIerrno\fR is clarified further for the file contexts backend: .RS .TP .B ENOENT No context corresponding to the \fIpath\fR and \fImode\fR was found - This will also be returned when the file contexts series of files have a context of \fB<>\fR against the \fIpath\fR (see the \fBFILE FORMAT\fR section). .RE .sp The \fIpath\fR argument should be set to the full pathname of the file whose assigned context is being checked. The \fImode\fR argument should be set to the mode bits of the file, as determined by \fBlstat\fR(2). \fImode\fR may be zero, however full matching may not occur. .sp Any messages generated by \fBselabel_lookup\fR(3) are sent to \fIstderr\fR by default, although this can be changed by \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) behaves identically to \fBselabel_lookup\fR(3) but does not perform context translation. .sp The \fBFILES\fR section details the configuration files used to determine a file context. . .SH "OPTIONS" In addition to the global options described in .BR selabel_open (3), this backend recognizes the following options: .RS .TP .B SELABEL_OPT_PATH A non-null value for this option specifies a path to a file that will be opened in lieu of the standard file contexts file. This value is also used as the base name for determining the names of local customization files. .TP .B SELABEL_OPT_BASEONLY A non-null value for this option indicates that any local customizations to the file contexts mapping should be ignored. .TP .B SELABEL_OPT_SUBSET A non-null value for this option is interpreted as a path prefix, for example "/etc". Only file context specifications with starting with a first component that prefix matches the given prefix are loaded. This may increase lookup performance, however any attempt to look up a path not starting with the given prefix may fail. This optimization is no longer required due to the use of .I file_contexts.bin files and is deprecated. .RE . .SH "FILES" The file context files used to retrieve the default context depends on the \fBSELABEL_OPT_PATH\fR parameter passed to \fBselabel_open\fR(3). If \fINULL\fR, then the \fBSELABEL_OPT_PATH\fR value will default to the active policy file contexts location (as returned by \fBselinux_file_context_path\fR(3)), otherwise the actual \fBSELABEL_OPT_PATH\fR value specified is used. .sp If \fBSELABEL_OPT_BASEONLY\fR is set, then the following files will be processed: .RS .IP "1." 4 The mandatory file contexts file that is either the fully qualified file name from \fISELABEL_OPT_PATH.value\fR or if \fINULL\fR, then the path returned by \fBselinux_file_context_path\fR(3). .IP "2." 4 The optional local and distribution substitution files that perform path aliasing on the 'in memory' version of the file contexts file. .br These files have the same name as the mandatory file contexts file with the extensions \fI.subs\fR and \fI.subs_dist\fR added. .RE .sp If the \fBSELABEL_OPT_BASEONLY\fR is not set, then the following files will be processed: .RS .IP "1." 4 The mandatory file contexts file that is either the fully qualified file name from \fISELABEL_OPT_PATH.value\fR or if \fINULL\fR, then the path returned by \fBselinux_file_context_path\fR(3). .IP "2." 4 The optional local customizations file that has the same name as the mandatory file contexts file with the extension \fI.local\fR added. .br \fBselinux_file_context_local_path\fR(3) will return the default path to this file. .IP "3." 4 The optional user home directory customizations file that has the same name as the mandatory file contexts file with the extension \fI.homedirs\fR added. .br \fBselinux_file_context_homedir_path\fR(3) will return the default path to this file. .IP "4." 4 The optional local and distribution substitution files that perform any path aliasing on the 'in memory' version of the file contexts file (and the \fI.local\fR and/or \fI.homedirs\fR if present). These files have the same name as the mandatory file contexts file with the extensions \fI.subs\fR and \fI.subs_dist\fR added. .br \fBselinux_file_context_subs_path\fR(3) and \fBselinux_file_context_subs_dist_path\fR(3) will return the default paths to these files. .RE .sp The default file context series of files are: .RS 6 .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.local .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.homedirs .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs_dist .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp Only the \fIfile_contexts\fR file is mandatory, the remainder are optional. .sp The entries within the file contexts series of files are shown in the \fBFILE FORMAT\fR section. . .SH "FILE FORMAT" .sp .SH "File Contexts Format" .sp Each line within the \fIfile_contexts\fR and the two customization files (\fI.local\fR and \fI.homedirs\fR) is as follows: .sp .RS .I pathname [file_type] context .RE .sp Where: .br .RS .I pathname .RS An entry that defines the pathname that may be in the form of a regular expression. .RE .I file_type .RS An optional file type consisting of: .RS \fI\-b\fR - Block Device \fI\-c\fR - Character Device .br \fI\-d\fR - Directory \fI\-p\fR - Named Pipe .br \fI\-l\fR - Symbolic Link \fI\-s\fR - Socket .br \fI\-\-\fR - Ordinary file .RE .RE .I context .RS This entry can be either: .RS .IP "a." 4 The security context that will be assigned to the file (i.e. returned as \fIcontext\fR). .IP "b." 4 A value of \fB<>\fR can be used to indicate that the matching files should not be re-labeled and causes \fBselabel_lookup\fR(3) to return \-1 with \fIerrno\fR set to \fBENOENT\fR. .RE .RE .RE .sp Example: .RS # ./contexts/files/file_contexts .br # pathname file_type context .br /.* system_u:object_r:default_t:s0 .br /[^/]+ \-\- system_u:object_r:etc_runtime_t:s0 .br /tmp/.* <> .RE .sp .SH "Substitution File Format" .sp Each line within the substitution files (\fI.subs\fR and \fI.subs_dist\fR) has the form: .RS .I subs_pathname pathname .RE .sp Where: .RS .I pathname .RS A path that matches an entry in one or more of the file contexts policy configuration file. .RE .I subs_pathname .RS The path that will be aliased (considered equivalent) with pathname by the look up process. .RE .RE .sp Example: .RS # ./contexts/files/file_contexts.subs .br # pathname subs_pathname .br /myweb /var/www .br /myspool /var/spool/mail .sp Using the above example, when \fBselabel_lookup\fR(3) is passed a path of \fI/myweb/index.html\fR the function will substitute the \fI/myweb\fR component with \fI/var/www\fR, therefore the path used is: .sp .RS .I /var/www/index.html .RE .RE . .SH "NOTES" .IP "1." 4 If contexts are to be validated, then the global option \fBSELABEL_OPT_VALIDATE\fR must be set before calling \fBselabel_open\fR(3). If this is not set, then it is possible for an invalid context to be returned. .IP "2." 4 If the size of file contexts series of files contain many entries, then \fBselabel_open\fR(3) may have a delay as it reads in the files, and if requested validates the entries. .IP "3." 4 Depending on the version of SELinux it is possible that a \fIfile_contexts.template\fR file may also be present, however this is now deprecated. .br The template file has the same format as the \fIfile_contexts\fR file and may also contain the keywords \fBHOME_ROOT\fR, \fBHOME_DIR\fR, \fBROLE\fR and \fBUSER\fR. This functionality has now been moved to the policy store and managed by \fBsemodule\fR(8) and \fBgenhomedircon\fR(8). . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_file_context_path "(3), " freecon "(3), " selinux_config "(5), " lstat "(2), "selinux_file_context_subs_path "(3), " selinux_file_context_subs_dist_path "(3), " selinux_file_context_homedir_path "(3), "selinux_file_context_local_path "(3), " semodule "(8), " genhomedircon "(8) " libselinux/man/man5/selabel_media.50100644 0000000 0000000 00000006425 13756670063 016256 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_media" "5" "29 Nov 2011" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_media \- userspace SELinux labeling interface and configuration file format for the media contexts backend . .SH "SYNOPSIS" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" device_name ", int " unused ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" device_name ", int " unused ");" . .SH "DESCRIPTION" The media contexts backend maps from media device names such as "cdrom" or "floppy" into security contexts. It is used to find the appropriate context for establishing context mounts on these devices. The returned \fIcontext\fR must be freed using \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) describes the function with its return and error codes. .sp The integer lookup argument is currently unused and should be set to zero. .sp Any messages generated by \fBselabel_lookup\fR(3) are sent to \fIstderr\fR by default, although this can be changed by \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) behaves identically to \fBselabel_lookup\fR(3) but does not perform context translation. .sp The \fBFILES\fR section details the configuration files used to determine the media context. . .SH "OPTIONS" In addition to the global options described in \fBselabel_open\fR(3), this backend recognizes the following options: .TP .B SELABEL_OPT_PATH A non-null value for this option specifies a path to a file that will be opened in lieu of the standard \fImedia\fR contexts file. . .SH "FILES" The media context file used to retrieve a default context depends on the \fBSELABEL_OPT_PATH\fR parameter passed to \fBselabel_open\FR(3). If \fINULL\fR, then the \fBSELABEL_OPT_PATH\fR value will default to the active policy media contexts location (as returned by \fBselinux_media_context_path\fR(3)), otherwise the actual \fBSELABEL_OPT_PATH\fR value specified is used. .sp The default media contexts file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/files/media .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" Each line within the \fImedia\fR file is as follows: .RS .I device_name context .RE .sp Where: .RS .I device_name .RS The media identifier (e.g. cdrom, floppy, disk and usb). .RE .I context .RS The context to be used for labeling the device. .RE .RE .sp Example: .RS # contexts/files/media .br cdrom system_u:object_r:removable_device_t .br floppy system_u:object_r:removable_device_t .br disk system_u:object_r:fixed_disk_device_t . .SH "NOTES" If contexts are to be validated, then the global option \fBSELABEL_OPT_VALIDATE\fR must be set before calling \fBselabel_open\fR(3). If this is not set, then it is possible for an invalid context to be returned. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_media_context_path "(3), " freecon "(3), " selinux_config "(5) " libselinux/man/man5/selabel_x.50100644 0000000 0000000 00000015004 13756670063 015437 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_x" "5" "29 Nov 2011" "Security Enhanced Linux" "SELinux API documentation" .SH "NAME" selabel_x \- userspace SELinux labeling interface and configuration file format for the X Window System contexts backend. This backend is also used to determine the default context for labeling remotely connected X clients . .SH "SYNOPSIS" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" . .SH "DESCRIPTION" The X contexts backend maps from X Window System object names into security contexts. It is used to find the appropriate context for X Window System objects whose significance and/or usage semantics are determined primarily by name. The returned \fIcontext\fR must be freed using \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) describes the function with its return and error codes. .sp This backend is also used to determine the default context for labeling remotely connected X clients. .sp The \fIobject_type\fR argument should be set to one of the following values: .RS .TP .B SELABEL_X_PROP The .I object_name argument specifies the name of a window property, such as "WM_NAME". .TP .B SELABEL_X_SELN The .I object_name argument specifies the name of a selection, such as "PRIMARY". .TP .B SELABEL_X_EXT The .I object_name argument specifies the name of a protocol extension, such as "RENDER". .TP .B SELABEL_X_EVENT The .I object_name argument specifies the name of an event type, such as "X11:ButtonPress". .TP .B SELABEL_X_CLIENT The .I object_name argument is ignored, however it should be set to either \fI*\fR (an asterisk or 'wildcard' that will select the default entry) or a specific entry such as "remote" in the X contexts file as shown in the \fBEXAMPLE\fR section. The default context for labeling remote X clients is then returned. .TP .B SELABEL_X_POLYPROP Like .BR SELABEL_X_PROP , but checks if the property was marked as being polyinstantiated. See \fBNOTES\fR below. .TP .B SELABEL_X_POLYSELN Like .BR SELABEL_X_SELN , but checks if the selection was marked as being polyinstantiated. See \fBNOTES\fR below. .RE .sp Any messages generated by \fBselabel_lookup\fR(3) are sent to \fIstderr\fR by default, although this can be changed by \fBselinux_set_callback\fR(3). .sp .B selabel_lookup_raw behaves identically to \fBselabel_lookup\fR but does not perform context translation. .sp The \fBFILES\fR section details the configuration files used to determine the X object context. . .SH "OPTIONS" In addition to the global options described in \fBselabel_open\fR(3), this backend recognizes the following options: .RS .TP .B SELABEL_OPT_PATH A non-null value for this option specifies a path to a file that will be opened in lieu of the standard X contexts file (see the \fBFILES\fR section for details). .RE . .SH "FILES" The X context file used to retrieve a default context depends on the \fBSELABEL_OPT_PATH\fR parameter passed to \fBselabel_open\fR(3). If \fINULL\fR, then the \fBSELABEL_OPT_PATH\fR value will default to the active policy X contexts location (as returned by \fBselinux_x_context_path\fR(3)), otherwise the actual \fBSELABEL_OPT_PATH\fR value specified is used. .sp The default X object contexts file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/x_contexts .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp The entries within the X contexts file are shown in the \fBObject Name String Values\fR and \fBFILE FORMAT\fR sections. . .SH "Object Name String Values" The string name assigned to each \fIobject_type\fR argument that can be present in the X contexts file are: .TS center, allbox, tab(@); lI lB lB l . object_type@Text Name SELABEL_X_PROP@property SELABEL_X_SELN@selection SELABEL_X_EXT@extension SELABEL_X_EVENT@event SELABEL_X_CLIENT@client SELABEL_X_POLYPROP@poly_property SELABEL_X_POLYSELN@poly_selection .TE . .SH "FILE FORMAT" Each line within the X contexts file is as follows: .RS .I object_type object_name context .RE .sp Where: .RS .I object_type .RS This is the string representation of the object type shown in the \fBObject Name String Values\fR section. There can be multiple lines with the same \fIobject_type\fR string that will form a block of entries (each with a different \fIobject_name\fR entry). .RE .I object_name .RS These are the object names of the specific X-server resource such as \fBPRIMARY\fR, \fBCUT_BUFFER0\fR etc. They are generally defined in the X-server source code (\fIprotocol.txt\fR and \fIBuiltInAtoms\fR in the dix directory of the xorg\-server source package). The entry can contain '*' for wildcard matching or '?' for substitution. Note that if the '*' is used, then be aware that the order of entries in the file is important. The '*' on its own is used to ensure a default fallback context is assigned and should be the last entry in the \fIobject_type\fR block. .RE .I context .RS The security context that will be applied to the object. .RE .RE .sp Example 1: .sp .nf # object_type object_name context selection PRIMARY system_u:object_r:clipboard_xselection_t:s0 selection * system_u:object_r:xselection_t:s0 .fi .sp Example 2 - This example shows how a client entry can be configured to ensure an entry is always found: .sp .nf # object_type object_name context client * system_u:object_r:remote_t:s0 .fi . .SH "NOTES" .IP "1." 4 Properties and selections are marked as either polyinstantiated or not. For these name types, the "POLY" option searches only the names marked as being polyinstantiated, while the other option searches only the names marked as not being polyinstantiated. Users of the interface should check both mappings, optionally taking action based on the result (e.g. polyinstantiating the object). .IP "2." 4 If contexts are to be validated, then the global option \fBSELABEL_OPT_VALIDATE\fR must be set before calling \fBselabel_open\fR(3). If this is not set, then it is possible for an invalid context to be returned. . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_x_context_path "(3), " freecon "(3), " selinux_config "(5) " libselinux/man/man5/sepgsql_contexts.50100644 0000000 0000000 00000000026 13756670063 017104 0ustar000000000 0000000 .so man5/selabel_db.5 libselinux/man/man5/service_seusers.50100644 0000000 0000000 00000003275 13756670063 016721 0ustar000000000 0000000 .TH "service_seusers" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" service_seusers \- The SELinux GNU/Linux user and service to SELinux user mapping configuration files . .SH "DESCRIPTION" These are optional files that allow services to define an SELinux user when authenticating via SELinux-aware login applications such as .BR PAM "(8). " .sp There is one file for each GNU/Linux user name that will be required to run a service with a specific SELinux user name. .sp The path for each configuration file is formed by the path returned by .BR selinux_policy_root "(3) with " .IR /logins/username appended (where \fIusername\fR is a file representing the GNU/Linux user name). The default services directory is located at: .RS .I /etc/selinux/{SELINUXTYPE}/logins .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp .BR getseuser "(3) reads this file to map services to an SELinux user. " . .SH "FILE FORMAT" Each line within the \fIusername\fR file is formatted as follows with each component separated by a colon: .RS .IB service : seuser \fR[\fB:\fIrange\fR] .RE .sp Where: .RS .I service .RS The service name used by the application. .RE .I seuser .RS The SELinux user name. .RE .I range .RS The range for MCS/MLS policies. .RE .RE . .SH "EXAMPLES" Example 1 - for the 'root' user: .RS # ./logins/root .br ipa:user_u:s0 .br this_service:unconfined_u:s0 .RE .sp Example 2 - for GNU/Linux user 'rch': .RS # ./logins/rch .br ipa:unconfined_u:s0 .br that_service:unconfined_u:s0 .RE . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " PAM "(8), " selinux_policy_root "(3), " getseuser "(3), " selinux_config "(5) " libselinux/man/man5/seusers.50100644 0000000 0000000 00000003074 13756670063 015176 0ustar000000000 0000000 .TH "seusers" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" seusers \- The SELinux GNU/Linux user to SELinux user mapping configuration file . .SH "DESCRIPTION" The .I seusers file contains a list GNU/Linux user to SELinux user mapping for use by SELinux-aware login applications such as \fBPAM\fR(8). .sp .BR selinux_usersconf_path "(3) " will return the active policy path to this file. The default SELinux users mapping file is located at: .RS .I /etc/selinux/{SELINUXTYPE}/seusers .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp .BR getseuserbyname "(3) reads this file to map a GNU/Linux user or group to an SELinux user. " . .SH "FILE FORMAT" Each line of the .I seusers configuration file consists of the following: .sp .RS \fR[\fB%\fIgroup_id\fR]|[\fIuser_id\fR]\fB:\fIseuser_id\fR[\fB:\fIrange\fR] .RE .sp Where: .RS \fIgroup_id\fR|\fIuser_id .RS \fRThe GNU/Linux user id, or if preceded by the percentage (\fB%\fR) symbol, then a GNU/Linux group id. .br An optional entry set to \fB__default__\fR can be provided as a fall back if required. .RE .I seuser_id .RS The SELinux user identity. .RE .I range .RS The optional level or range for an MLS/MCS policy. .RE .RE . .SH "EXAMPLE" # ./seusers .br system_u:system_u:s0\-s15:c0.c255 .br root:root:s0\-s15:c0.c255 .br fred:user_u:s0 .br __default__:user_u:s0 .br %user_group:user_u:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " PAM "(8), " selinux_usersconf_path "(3), " getseuserbyname "(3), " selinux_config "(5) " libselinux/man/man5/user_contexts.50100644 0000000 0000000 00000005210 13756670063 016404 0ustar000000000 0000000 .TH "user_contexts" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" user_contexts \- The SELinux user contexts configuration files . .SH "DESCRIPTION" These optional user context configuration files contain entries that allow SELinux-aware login applications such as .BR PAM (8) (running in their own process context), to determine the context that a users login session should run under. .sp SELinux-aware login applications generally use one or more of the following libselinux functions that read these files from the active policy path: .RS .BR get_default_context (3) .br .BR get_ordered_context_list (3) .br .BR get_ordered_context_list_with_level (3) .br .BR get_default_context_with_level (3) .br .BR get_default_context_with_role (3) .br .BR get_default_context_with_rolelevel (3) .br .BR query_user_context (3) .br .BR manual_user_enter_context (3) .RE .sp There can be one file for each SELinux user configured on the system. The file path is formed using the path returned by .BR \%selinux_user_contexts_path (3) for the active policy, with the SELinux user name appended, for example: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/users/unconfined_u .br .I /etc/selinux/{SELINUXTYPE}/contexts/users/xguest_u .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). .sp These files contain context information as described in the .B FILE FORMAT section. . .SH "FILE FORMAT" Each line in the user context configuration file consists of the following: .RS .I login_process user_login_process .RE .sp Where: .RS .I login_process .RS This consists of a \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] entry that represents the login process context. .RE .I user_login_process .RS This consists of a \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] entry that represents the user login process context. .RE .RE . .SH "EXAMPLE" # Example for xguest_u at /etc/selinux/targeted/contexts/users/xguest_u .br system_r:crond_t:s0 xguest_r:xguest_t:s0 .br system_r:initrc_t:s0 xguest_r:xguest_t:s0 .br system_r:local_login_t:s0 xguest_r:xguest_t:s0 .br system_r:remote_login_t:s0 xguest_r:xguest_t:s0 .br system_r:sshd_t:s0 xguest_r:xguest_t:s0 .br system_r:xdm_t:s0 xguest_r:xguest_t:s0 .br xguest_r:xguest_t:s0 xguest_r:xguest_t:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " selinux_user_contexts_path "(3), " PAM "(8), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " libselinux/man/man5/virtual_domain_context.50100644 0000000 0000000 00000002326 13756670063 020265 0ustar000000000 0000000 .TH "virtual_domain_context" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" virtual_domain_context \- The SELinux virtual machine domain context configuration file . .SH "DESCRIPTION" The .I virtual_domain_context file contains a list of domain contexts that are available for use by the SELinux-aware virtualization API libvirt (see \fBlibvirtd\fR(8)). .sp .BR selinux_virtual_domain_context_path "(3) " will return the active policy path to this file. The default virtual domain context file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/virtual_domain_context .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" Each line in the file consists of an entry as follows: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Where: .RS .I user role type range .RS A user, role, type and optional range (for MCS/MLS) separated by colons (:) that can be used as a virtual domain context. .RE .RE . .SH "EXAMPLE" # ./contexts/virtual_domain_context .br system_u:object_r:svirt_t:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " libvirtd "(8), " selinux_virtual_domain_context_path "(3), " selinux_config "(5) " libselinux/man/man5/virtual_image_context.50100644 0000000 0000000 00000002347 13756670063 020103 0ustar000000000 0000000 .TH "virtual_image_context" "5" "28-Nov-2011" "Security Enhanced Linux" "SELinux configuration" .SH "NAME" virtual_image_context \- The SELinux virtual machine image context configuration file . .SH "DESCRIPTION" The .I virtual_image_context file contains a list of image contexts for use by the SELinux-aware virtualization API libvirt (see \fBlibvirtd\fR(8)). .sp .BR selinux_virtual_image_context_path "(3) " will return the active policy path to this file. The default virtual image context file is: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/virtual_image_context .RE .sp Where \fI{SELINUXTYPE}\fR is the entry from the selinux configuration file \fIconfig\fR (see \fBselinux_config\fR(5)). . .SH "FILE FORMAT" Each line in the file consists of an entry as follows: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Where: .RS .I user role type range .RS A user, role, type and optional range (for MCS/MLS) separated by colons (:) that can be used as a virtual image context. .RE .RE . .SH "EXAMPLE" # ./contexts/virtual_image_context .br system_u:object_r:svirt_image_t:s0 .br system_u:object_r:svirt_content_t:s0 . .SH "SEE ALSO" .ad l .nh .BR selinux "(8), " libvirtd "(8), " selinux_virtual_image_context_path "(3), " selinux_config "(5) " libselinux/man/man5/x_contexts.50100644 0000000 0000000 00000000025 13756670063 015674 0ustar000000000 0000000 .so man5/selabel_x.5 libselinux/man/man8/0040755 0000000 0000000 00000000000 13756670063 013421 5ustar000000000 0000000 libselinux/man/man8/avcstat.80100644 0000000 0000000 00000001423 13756670063 015154 0ustar000000000 0000000 .TH "avcstat" "8" "18 Nov 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" avcstat \- Display SELinux AVC statistics . .SH "SYNOPSIS" .B avcstat .RB [ \-c ] .RB [ \-f .IR status_file ] .RI [ interval ] . .SH "DESCRIPTION" Display SELinux AVC statistics. If the .I interval parameter is specified, the program will loop, displaying updated statistics every .I interval seconds. Relative values are displayed by default. . .SH OPTIONS .TP .B \-c Display the cumulative values. .TP .B \-f Specifies the location of the AVC statistics file, defaulting to .IR /sys/fs/selinux/avc/cache_stats . . .SH AUTHOR This manual page was written by Dan Walsh . The program was written by James Morris . . .SH "SEE ALSO" .BR selinux (8) libselinux/man/man8/booleans.80100644 0000000 0000000 00000003503 13756670063 015312 0ustar000000000 0000000 .TH "booleans" "8" "11 Aug 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" booleans \- Policy booleans enable runtime customization of SELinux policy . .SH "DESCRIPTION" This manual page describes SELinux policy booleans. .BR The SELinux policy can include conditional rules that are enabled or disabled based on the current values of a set of policy booleans. These policy booleans allow runtime modification of the security policy without having to load a new policy. For example, the boolean httpd_enable_cgi allows the httpd daemon to run cgi scripts if it is enabled. If the administrator does not want to allow execution of cgi scripts, he can simply disable this boolean value. The policy defines a default value for each boolean, typically false. These default values can be overridden via local settings created via the .BR setsebool (8) utility, using .B \-P to make the setting persistent across reboots. The .B system\-config\-securitylevel tool provides a graphical interface for altering the settings. The .BR load_policy (8) program will preserve current boolean settings upon a policy reload by default, or can optionally reset booleans to the boot-time defaults via the .B \-b option. Boolean values can be listed by using the .BR getsebool (8) utility and passing it the .B \-a option. Boolean values can also be changed at runtime via the .BR setsebool (8) utility or the .BR togglesebool (8) utility. By default, these utilities only change the current boolean value and do not affect the persistent settings, unless the .B \-P option is used to setsebool. . .SH AUTHOR This manual page was written by Dan Walsh . The SELinux conditional policy support was developed by Tresys Technology. . .SH "SEE ALSO" .BR getsebool (8), .BR setsebool (8), .BR selinux (8), .BR togglesebool (8) libselinux/man/man8/getenforce.80100644 0000000 0000000 00000000617 13756670063 015634 0ustar000000000 0000000 .TH "getenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" getenforce \- get the current mode of SELinux . .SH "SYNOPSIS" .B getenforce . .SH "DESCRIPTION" .B getenforce reports whether SELinux is enforcing, permissive, or disabled. . .SH AUTHOR Dan Walsh, . .SH "SEE ALSO" .BR selinux (8), .BR setenforce (8), .BR selinuxenabled (8) libselinux/man/man8/getsebool.80100644 0000000 0000000 00000002145 13756670063 015474 0ustar000000000 0000000 .TH "getsebool" "8" "11 Aug 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" getsebool \- get SELinux boolean value(s) . .SH "SYNOPSIS" .B getsebool .RB [ \-a ] .RI [ boolean ] . .SH "DESCRIPTION" .B getsebool reports where a particular SELinux boolean or all SELinux booleans are on or off In certain situations a boolean can be in one state with a pending change to the other state. getsebool will report this as a pending change. The pending value indicates the value that will be applied upon the next boolean commit. The setting of boolean values occurs in two stages; first the pending value is changed, then the booleans are committed, causing their active values to become their pending values. This allows a group of booleans to be changed in a single transaction, by setting all of their pending values as desired and then committing once. . .SH OPTIONS .TP .B \-a Show all SELinux booleans. . .SH AUTHOR This manual page was written by Dan Walsh . The program was written by Tresys Technology. . .SH "SEE ALSO" .BR selinux (8), .BR setsebool (8), .BR booleans (8) libselinux/man/man8/matchpathcon.80100644 0000000 0000000 00000002740 13756670063 016163 0ustar000000000 0000000 .TH "matchpathcon" "8" "21 April 2005" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" matchpathcon \- get the default SELinux security context for the specified path from the file contexts configuration . .SH "SYNOPSIS" .B matchpathcon .RB [ \-V ] .RB [ \-N ] .RB [ \-n ] .RB [ \-m .IR type ] .RB [ \-f .IR file_contexts_file ] .RB [ \-p .IR prefix ] .RB [ \-P .IR policy_root_path ] .I filepath... . .SH "DESCRIPTION" .BR matchpathcon queries the system policy and outputs the default security context associated with the filepath. .B Note: Identical paths can have different security contexts, depending on the file type (regular file, directory, link file, char file ...). .B matchpathcon will also take the file type into consideration in determining the default security context if the file exists. If the file does not exist, no file type matching will occur. . .SH OPTIONS .TP .BI \-m " type" Force file type for the lookup. Valid types are .BR file ", " dir ", "pipe ", " chr_file ", " blk_file ", " .BR lnk_file ", " sock_file . .TP .B \-n Do not display path. .TP .B \-N Do not use translations. .TP .BI \-f " file_context_file" Use alternate file_context file .TP .BI \-p " prefix" Use prefix to speed translations .TP .BI \-P " policy_root_path" Use alternate policy root path .TP .B \-V Verify file context on disk matches defaults . .SH AUTHOR This manual page was written by Dan Walsh . . .SH "SEE ALSO" .BR selinux "(8), " .BR matchpathcon (3) libselinux/man/man8/sefcontext_compile.80100644 0000000 0000000 00000003003 13756670063 017375 0ustar000000000 0000000 .TH "sefcontext_compile" "8" "12 Aug 2015" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" sefcontext_compile \- compile file context regular expression files . .SH "SYNOPSIS" .B sefcontext_compile .RB [ \-o .IR outputfile ] .RB [ \-p .IR policyfile ] .I inputfile . .SH "DESCRIPTION" .B sefcontext_compile is used to compile file context regular expressions into .BR pcre (3) format. .sp The compiled file is used by libselinux file labeling functions. .sp By default .B sefcontext_compile writes the compiled pcre file with the .B .bin suffix appended (e.g. \fIinputfile\fB.bin\fR). .SH OPTIONS .TP .B \-o Specify an .I outputfile that must be a fully qualified file name as the .B .bin suffix is not automatically added. .TP .B \-p Specify a binary .I policyfile that will be used to validate the context entries in the .I inputfile .br If an invalid context is found the pcre formatted file will not be written and an error will be returned. .SH "RETURN VALUE" On error -1 is returned. On success 0 is returned. .SH "EXAMPLES" .B Example 1: .br sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts .sp Results in the following file being generated: .RS /etc/selinux/targeted/contexts/files/file_contexts.bin .RE .sp .B Example 2: .br sefcontext_compile -o new_fc.bin /etc/selinux/targeted/contexts/files/file_contexts .sp Results in the following file being generated in the cwd: .RS new_fc.bin .RE . .SH AUTHOR Dan Walsh, . .SH "SEE ALSO" .BR selinux (8), .BR semanage (8), libselinux/man/man8/selinux.80100644 0000000 0000000 00000010722 13756670063 015200 0ustar000000000 0000000 .TH "selinux" "8" "29 Apr 2005" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" SELinux \- NSA Security-Enhanced Linux (SELinux) . .SH "DESCRIPTION" NSA Security-Enhanced Linux (SELinux) is an implementation of a flexible mandatory access control architecture in the Linux operating system. The SELinux architecture provides general support for the enforcement of many kinds of mandatory access control policies, including those based on the concepts of Type Enforcement®, Role- Based Access Control, and Multi-Level Security. Background information and technical documentation about SELinux can be found at http://www.nsa.gov/research/selinux. The .I /etc/selinux/config configuration file controls whether SELinux is enabled or disabled, and if enabled, whether SELinux operates in permissive mode or enforcing mode. The .B SELINUX variable may be set to any one of disabled, permissive, or enforcing to select one of these options. The disabled option completely disables the SELinux kernel and application code, leaving the system running without any SELinux protection. The permissive option enables the SELinux code, but causes it to operate in a mode where accesses that would be denied by policy are permitted but audited. The enforcing option enables the SELinux code and causes it to enforce access denials as well as auditing them. Permissive mode may yield a different set of denials than enforcing mode, both because enforcing mode will prevent an operation from proceeding past the first denial and because some application code will fall back to a less privileged mode of operation if denied access. The .I /etc/selinux/config configuration file also controls what policy is active on the system. SELinux allows for multiple policies to be installed on the system, but only one policy may be active at any given time. At present, multiple kinds of SELinux policy exist: targeted, mls for example. The targeted policy is designed as a policy where most user processes operate without restrictions, and only specific services are placed into distinct security domains that are confined by the policy. For example, the user would run in a completely unconfined domain while the named daemon or apache daemon would run in a specific domain tailored to its operation. The MLS (Multi-Level Security) policy is designed as a policy where all processes are partitioned into fine-grained security domains and confined by policy. MLS also supports the Bell And LaPadula model, where processes are not only confined by the type but also the level of the data. You can define which policy you will run by setting the .B SELINUXTYPE environment variable within .IR /etc/selinux/config . You must reboot and possibly relabel if you change the policy type to have it take effect on the system. The corresponding policy configuration for each such policy must be installed in the .I /etc/selinux/{SELINUXTYPE}/ directories. A given SELinux policy can be customized further based on a set of compile-time tunable options and a set of runtime policy booleans. .B \%system\-config\-selinux allows customization of these booleans and tunables. Many domains that are protected by SELinux also include SELinux man pages explaining how to customize their policy. . .SH "FILE LABELING" All files, directories, devices ... have a security context/label associated with them. These context are stored in the extended attributes of the file system. Problems with SELinux often arise from the file system being mislabeled. This can be caused by booting the machine with a non SELinux kernel. If you see an error message containing file_t, that is usually a good indicator that you have a serious problem with file system labeling. The best way to relabel the file system is to create the flag file .I /.autorelabel and reboot. .BR system\-config\-selinux , also has this capability. The .BR restorecon / fixfiles commands are also available for relabeling files. . .SH AUTHOR This manual page was written by Dan Walsh . . .SH FILES .I /etc/selinux/config . .SH "SEE ALSO" .ad l .nh .BR booleans (8), .BR setsebool (8), .BR sepolicy (8), .BR system-config-selinux (8), .BR togglesebool (8), .BR restorecon (8), .BR fixfiles (8), .BR setfiles (8), .BR semanage (8), .BR sepolicy (8) Every confined service on the system has a man page in the following format: .br .BR _selinux (8) For example, httpd has the .BR httpd_selinux (8) man page. .B man -k selinux Will list all SELinux man pages. libselinux/man/man8/selinuxenabled.80100644 0000000 0000000 00000001001 13756670063 016501 0ustar000000000 0000000 .TH "selinuxenabled" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" selinuxenabled \- tool to be used within shell scripts to determine if selinux is enabled . .SH "SYNOPSIS" .B selinuxenabled . .SH "DESCRIPTION" Indicates whether SELinux is enabled or disabled. . .SH "EXIT STATUS" It exits with status 0 if SELinux is enabled and 1 if it is not enabled. . .SH AUTHOR Dan Walsh, . .SH "SEE ALSO" .BR selinux (8), .BR setenforce (8), .BR getenforce (8) libselinux/man/man8/selinuxexeccon.80100644 0000000 0000000 00000001262 13756670063 016544 0ustar000000000 0000000 .TH "selinuxexeccon" "8" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" selinuxexeccon \- report SELinux context used for this executable . .SH "SYNOPSIS" .B selinuxexeccon .I command .RI [ fromcon ] . .SH "DESCRIPTION" .B selinuxexeccon reports the SELinux process context for the specified command from the specified context or the current context. . .SH EXAMPLE .nf # selinuxexeccon /usr/bin/passwd staff_u:staff_r:passwd_t:s0-s0:c0.c1023 # selinuxexeccon /usr/sbin/sendmail system_u:system_r:httpd_t:s0 system_u:system_r:system_mail_t:s0 .fi . .SH AUTHOR This manual page was written by Dan Walsh . . .SH "SEE ALSO" .BR secon (8) libselinux/man/man8/setenforce.80100644 0000000 0000000 00000001155 13756670063 015646 0ustar000000000 0000000 .TH "setenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" setenforce \- modify the mode SELinux is running in . .SH "SYNOPSIS" .B setenforce .RB [ Enforcing | Permissive | 1 | 0 ] . .SH "DESCRIPTION" Use .B Enforcing or .B 1 to put SELinux in enforcing mode. .br Use .B Permissive or .B 0 to put SELinux in permissive mode. If SELinux is disabled and you want to enable it, or SELinux is enabled and you want to disable it, please see .BR selinux (8). . .SH AUTHOR Dan Walsh, . .SH "SEE ALSO" .BR selinux (8), .BR getenforce (8), .BR selinuxenabled (8) libselinux/man/man8/togglesebool.80100644 0000000 0000000 00000001151 13756670063 016172 0ustar000000000 0000000 .TH "togglesebool" "8" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation" .SH "NAME" togglesebool \- flip the current value of a SELinux boolean . .SH "SYNOPSIS" .B togglesebool .I boolean... . .SH "DESCRIPTION" .B togglesebool flips the current value of a list of booleans. If the value is currently a 1, then it will be changed to a 0 and vice versa. Only the "in memory" values are changed; the boot-time settings are unaffected. . .SH AUTHOR This man page was written by Steve Grubb . .SH "SEE ALSO" .BR selinux (8), .BR booleans (8), .BR getsebool (8), .BR setsebool (8) libselinux/man/ru/0040755 0000000 0000000 00000000000 13756670063 013204 5ustar000000000 0000000 libselinux/man/ru/man5/0040755 0000000 0000000 00000000000 13756670063 014044 5ustar000000000 0000000 libselinux/man/ru/man5/booleans.50100644 0000000 0000000 00000007434 13756670063 015741 0ustar000000000 0000000 .TH "booleans" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" booleans \- файлы конфигурации логических переключателей SELinux . .SH "ОПИСАНИЕ" Файл \fIbooleans\fR (если имеется) содержит логические переключатели, обеспечивающие поддержку определённого дистрибутива. .sp Файл \fIbooleans.local\fR (если имеется) содержит созданные локально логические переключатели. .sp Оба файла содержат список имён логических переключателей и соответствующих этим именам значений. .sp Обычно файл \fIbooleans\fR и/или файл \fIbooleans.local\fR отсутствуют (они устарели). Но эти файлы могут присутствовать, если имеется приложение, которое поддерживает SELinux и использует перечисленные далее функции libselinux: .sp .RS .BR security_set_boolean_list "(3) " .RS Записывает файл \fIbooleans.local\fR, если флаг \fIpermanent\fR = \fI1\fR. .sp .RE .RE .RS .BR security_load_booleans "(3) " .RS Выполняет поиск файла \fIbooleans\fR и/или файла \fIbooleans.local\fR по адресу \fBselinux_booleans_path\fR(3) (если в качестве параметра не указан конкретный путь). .RE .RE .sp \fBbooleans\fR(8) содержит подробные сведения о логических переключателях, а \fBsetsebool\fR(8) - описание того, как установить логические переключатели, которые не будут сбрасываться при перезагрузках. .sp \fBselinux_booleans_path\fR(3) вернёт путь активной политики к этим файлам. Файлы логических переключателей по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/booleans .br .I /etc/selinux/{SELINUXTYPE}/booleans.local .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Оба файла имеют один и тот же формат и содержат одно или несколько имён логических переключателей и их значения. .sp Формат: .RS .I boolean_name .I value .sp .RE Где: .RS .I boolean_name .RS Имя логического переключателя. .RE .I value .RS Значение логического переключателя по умолчанию. Может быть одним из следующих: .RS .IR true " | " false " | " 1 " | " 0 .RE .RE .RE .sp Если .B SETLOCALDEFS указано в файле .I config SELinux (см. .BR selinux_config "(5)), то " selinux_mkload_policy "(3) будет проверять наличие файла " .I booleans.local по адресу .BR selinux_booleans_path (3), а также файла .I local.users (см. .BR local.users "(5)) по адресу " selinux_users_path "(3). " . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " booleans "(8), " setsebool "(8), " semanage "(8), " selinux_booleans_path "(3), " security_set_boolean_list "(3), " security_load_booleans "(3), " selinux_mkload_policy "(3), " selinux_users_path "(3), " selinux_config "(5), " local.users "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/customizable_types.50100644 0000000 0000000 00000005453 13756670063 020063 0ustar000000000 0000000 .TH "customizable_types" "5" "28 ноября 2011" "Security Enhanced Linux" "SELinux configuration" .SH "ИМЯ" customizable_types \- файл конфигурации настраиваемых типов SELinux . .SH "ОПИСАНИЕ" Файл \fIcustomizable_types\fR содержит список типов, которые можно каким-либо образом настраивать с помощью поддерживающих SELinux приложений. .sp Обычно это тип контекста файла, который устанавливается для файлов, к которым требуется предоставить общий доступ для определённых доменов, и когда администратору необходимо управлять этим типом вручную. .sp Возможность использования настраиваемых типов устарела. Рекомендуется использовать .BR semanage (8) .BR fcontext (8) .BR ... (8). Тем не менее, поддерживающие SELinux приложения, например, .BR setfiles (8), будут использовать эту информацию для получения списка типов, относящихся к файлам, для которых не следует повторно проставлять метки. .sp .BR selinux_customizable_types_path (3) вернёт путь активной политики к этому файлу. Файл настраиваемых типов по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/customizable_types .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp .BR is_context_customizable (3) выполняет чтение этого файла, чтобы определить, является ли контекст настраиваемым для активной политики. . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле состоит из следующих компонентов: .RS .I type .RE .sp Где: .RS .I type .RS Определённый в политике тип, который можно настроить. .RE .RE . .SH "ПРИМЕР" # ./contexts/customizable_types .br mount_loopback_t .br public_content_rw_t .br public_content_t .br swapfile_t .br sysadm_untrusted_content_t . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selinux_customizable_types_path "(3), " is_context_customizable "(3), " semanage "(8), " setfiles "(8), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/default_contexts.50100644 0000000 0000000 00000006750 13756670063 017512 0ustar000000000 0000000 .TH "default_contexts" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" default_contexts \- файл конфигурации контекстов SELinux по умолчанию . .SH "ОПИСАНИЕ" Файл конфигурации контекстов по умолчанию \fIdefault_contexts\fR содержит записи, которые позволяют поддерживающим SELinux приложениям для входа, например, .BR PAM "(8), настроить контекст пользователя. " .sp Поддерживающие SELinux приложения для входа обычно используют одну или несколько из следующих функций libselinux, которые выполняют чтение этих файлов по пути активной политики: .RS .BR get_default_context "(3) " .br .BR get_ordered_context_list "(3) " .br .BR get_ordered_context_list_with_level "(3) " .br .BR get_default_context_with_level "(3) " .br .BR get_default_context_with_role "(3) " .br .BR get_default_context_with_rolelevel "(3) " .br .BR query_user_context "(3) " .br .BR manual_user_enter_context "(3) " .RE .sp Путь к файлу конфигурации контекстов по умолчанию для активной политики возвращает \fBselinux_default_contexts_path\fR(3). По умолчанию файл контекстов по умолчанию находится по адресу: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/default_contexts .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле конфигурации по умолчанию состоит из следующих компонентов: .RS .I login_process user_login_process [user_login_process] ... .RE .sp Где: .RS .I login_process .RS Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа, определённый в политике. .RE .I user_login_process .RS Состоит из одной или нескольких записей \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которые представляют собой контекст процесса входа пользователя, определённый в политике. .RE .RE . .SH "ПРИМЕР" # ./contexts/default_contexts .br system_r:crond_t:s0 system_r:system_crond_t:s0 .br system_r:local_login_t:s0 user_r:user_t:s0 staff_r:staff_t:s0 .br system_r:remote_login_t:s0 user_r:user_t:s0 .br system_r:sshd_t:s0 user_r:user_t:s0 .br system_r:sulogin_t:s0 sysadm_r:sysadm_t:s0 .br system_r:xdm_t:s0 user_r:user_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selinux_default_contexts_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/default_type.50100644 0000000 0000000 00000003444 13756670063 016621 0ustar000000000 0000000 .TH "default_type" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" default_type \- файл конфигурации типов SELinux по умолчанию . .SH "ОПИСАНИЕ" Файл \fIdefault_type\fR содержит записи, которые позволяют поддерживающим SELinux приложениям, таким как \fBnewrole\fR(1), выбирать для роли тип по умолчанию, если не предоставлен другой тип. .sp \fBselinux_default_type_path\fR(3) возвращает путь активной политики к этому файлу. По умолчанию файл типов по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/default_type .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp \fBget_default_type\fR(3) выполняет чтение этого файла, чтобы определить тип для активной политики. . .SH "ФОРМАТ ФАЙЛА" Каждая строка внутри файла \fIdefault_type\fR форматируется записями \fIrole\fB:\fItype\fR, где: .RS .I role .RS Роль SELinux. .RE .I type .RS Тип домена, который возвращается для этой роли. .RE . .SH "ПРИМЕР" # ./contexts/default_type .br auditadm_r:auditadm_t .br user_r:user_t . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " get_default_type "(3), " newrole "(1), " selinux_default_type_path "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/failsafe_context.50100644 0000000 0000000 00000005516 13756670063 017454 0ustar000000000 0000000 .TH "failsafe_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" failsafe_context \- файл конфигурации надёжного контекста SELinux . .SH "ОПИСАНИЕ" Файл .I failsafe_context позволяет поддерживающим SELinux приложениям, таким как .BR PAM "(8), " получать известный действительный контекст входа для администратора, если в других расположениях отсутствуют действительные записи по умолчанию. .sp .BR selinux_failsafe_context_path "(3) " возвращает путь активной политики к этому файлу. Файл надёжного контекста по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/failsafe_context .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp Следующие функции выполняют чтение этого файла по пути активной политики, если им не удаётся получить контекст по умолчанию: .br .RS .BR get_default_context "(3) " .br .BR get_ordered_context_list "(3) " .br .BR get_ordered_context_list_with_level "(3) " .br .BR get_default_context_with_level "(3) " .br .BR get_default_context_with_role "(3) " .br .BR get_default_context_with_rolelevel "(3) " .br .BR query_user_context "(3) " .br .BR manual_user_enter_context "(3) " .RE . .SH "ФОРМАТ ФАЙЛА" Файл состоит из следующей однострочной записи: .RS \fIrole\fB:\fItype\fR[\fB:\fIrange\fR] .RE .sp Где: .RS .I role .I type .I range .RS Роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые формируют действительный контекст процесса входа для получения администратором доступа к системе. .RE .RE . .SH "ПРИМЕР" # ./contexts/failsafe_context .br unconfined_r:unconfined_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selinux_failsafe_context_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/file_contexts.50100644 0000000 0000000 00000000030 13756670063 016766 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/ru/man5/file_contexts.homedirs.50100644 0000000 0000000 00000000030 13756670063 020577 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/ru/man5/file_contexts.local.50100644 0000000 0000000 00000000030 13756670063 020057 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/ru/man5/file_contexts.subs.50100644 0000000 0000000 00000000030 13756670063 017741 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/ru/man5/file_contexts.subs_dist.50100644 0000000 0000000 00000000030 13756670063 020764 0ustar000000000 0000000 .so man5/selabel_file.5 libselinux/man/ru/man5/local.users.50100644 0000000 0000000 00000006512 13756670063 016365 0ustar000000000 0000000 .TH "local.users" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" local.users \- файл конфигурации локальных пользователей SELinux . .SH "ОПИСАНИЕ" Файл содержит определения локальных пользователей в виде инструкций пользователей на языке политики. Этот файл имеется только в старых версиях систем SELinux, так как он устарел и был заменён службами \fBsemanage\fR(8). .sp \fBselinux_mkload_policy\fR(3) выполняет чтение этого файла только тогда, когда для \fBSETLOCALDEFS\fR в файле \fIconfig\fR SELinux (см. \fBselinux_config\fR(5)) установлено значение \fI1\fR. .sp .BR selinux_users_path "(3) " возвращает путь активной политики к каталогу, в котором расположен файл. Файл локальных пользователей по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/users/local.users .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Файл состоит из одной или нескольких записей, которые заканчиваются '\fB;\fR', каждая на отдельной строке: .RS \fBuser \fIseuser_id \fBroles \fIrole_id\fR [[\fBlevel \fIlevel\fR] [\fBrange \fIrange\fR]]\fB;\fR .RE .sp Где: .RS .B user .RS Ключевое слово user (пользователь). .RE .I seuser_id .RS Идентификатор пользователя SELinux. .RE .B roles .RS Ключевое слово roles (роли). .RE .I role_id .RS Один или несколько ранее объявленных идентификаторов ролей. Несколько идентификаторов ролей - это разделённый пробелами список, который заключён в скобки '{}'. .RE .B level .RS Если настроена система MLS/MCS, ключевое слово level (уровень). .RE .I level .RS Уровень безопасности пользователя по умолчанию. Обратите внимание, что обязательным является только компонент конфиденциальности уровня (например, s0). .RE .B range .RS Если настроена система MLS/MCS, ключевое слово range (диапазон). .RE .I range .RS Текущий уровень и уровень допуска пользователя. Они разделены дефисом '\fB-\fR' (как показано в разделе \fBПРИМЕР\fR). .RE .RE . .SH "ПРИМЕР" # ./users/local.users .br user test_u roles staff_r level s0 range s0 \- s15:c0.c1023; . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " semanage "(8), " selinux_users_path "(3), " selinux_config "(5), " selinux_mkload_policy "(3) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/media.50100644 0000000 0000000 00000000031 13756670063 015200 0ustar000000000 0000000 .so man5/selabel_media.5 libselinux/man/ru/man5/removable_context.50100644 0000000 0000000 00000003207 13756670063 017651 0ustar000000000 0000000 .TH "removable_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" removable_context \- файл конфигурации SELinux-контекста съёмных устройств . .SH "ОПИСАНИЕ" Этот файл содержит метку по умолчанию, которую следует использовать для съёмных устройств. .sp .BR selinux_removable_context_path "(3) " вернёт путь активной политики к этому файлу. Файл контекста съёмных устройств по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/removable_context .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Файл состоит из следующей однострочной записи: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Где: .RS .I user role type range .RS Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые будут применены к съёмным устройствам. .RE .RE . .SH "ПРИМЕР" # ./contexts/removable_contexts .br system_u:object_r:removable_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux "(8), " selinux_removable_context_path "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/secolor.conf.50100644 0000000 0000000 00000010725 13756670063 016526 0ustar000000000 0000000 .TH "secolor.conf" "5" "08 апреля 2011" "Документация API SELinux" .SH "ИМЯ" secolor.conf \- файл конфигурации цвета SELinux . .SH "ОПИСАНИЕ" Этот необязательный файл управляет цветом, который назначается компонентам контекста, связанным с контекстом .I raw , который передаётся с помощью .BR selinux_raw_context_to_color "(3)," когда поддерживающее SELinux приложение должно показать сведения о контексте в цвете. .sp .BR selinux_raw_context_to_color "(3)" получает эту информацию о цвете из файла активной политики .B secolor.conf , возвращённого .BR selinux_colors_path "(3)." . .SH "ФОРМАТ ФАЙЛА" Формат файла: .RS .B color .I color_name .BI "= #"color_mask .br [...] .sp .I context_component string .B = .I fg_color_name bg_color_name .br [...] .sp .RE Где: .br .B color .RS Ключевое слово цвета (color). Каждая запись цвета находится на новой строке. .RE .I color_name .RS Название цвета из одного слова (например, red (красный)). .RE .I color_mask .RS Маска цвета, начинающаяся с хэша (#), который описывает шестнадцатиричные RGB-цвета, где black (чёрный) #000000 и white (белый) #ffffff. .RE .I context_component .RS Имя компонента контекста, должно быть одним из следующих: .br .RS пользователь, роль, тип или диапазон .RE Каждая запись .IR context_component " " string " ..." находится на новой строке. .RE .I string .RS Это строка .I context_component , которая будет сопоставляться с компонентом контекста .I raw , который передаётся .BR selinux_raw_context_to_color "(3)." .br Подстановочный знак '*' можно использовать для сопоставления какой-либо неопределённой строки только записям .I context_component пользователя, роли или типа. .RE .I fg_color_name .RS Строка color_name, которая будет использоваться как цвет переднего плана. Маска цвета .I color_mask также может использоваться. .RE .I bg_color_name .RS Строка color_name, которая будет использоваться как цвет фона. Маска цвета .I color_mask также может использоваться. .RE . .SH "ПРИМЕРЫ" Записи примера 1: .RS color black = #000000 .br color green = #008000 .br color yellow = #ffff00 .br color blue = #0000ff .br color white = #ffffff .br color red = #ff0000 .br color orange = #ffa500 .br color tan = #D2B48C .sp user * = black white .br role * = white black .br type * = tan orange .br range s0\-s0:c0.c1023 = black green .br range s1\-s1:c0.c1023 = white green .br range s3\-s3:c0.c1023 = black tan .br range s5\-s5:c0.c1023 = white blue .br range s7\-s7:c0.c1023 = black red .br range s9\-s9:c0.c1023 = black orange .br range s15:c0.c1023 = black yellow .RE .sp Записи примера 2: .RS color black = #000000 .br color green = #008000 .br color yellow = #ffff00 .br color blue = #0000ff .br color white = #ffffff .br color red = #ff0000 .br color orange = #ffa500 .br color tan = #d2b48c .sp user unconfined_u = #ff0000 green .br role unconfined_r = red #ffffff .br type unconfined_t = red orange .br user user_u = black green .br role user_r = white black .br type user_t = tan red .br user xguest_u = black yellow .br role xguest_r = black red .br type xguest_t = black green .br user sysadm_u = white black .br range s0:c0.c1023 = black white .br user * = black white .br role * = black white .br type * = black white .RE . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/securetty_types.50100644 0000000 0000000 00000004143 13756670063 017404 0ustar000000000 0000000 .TH "securetty_types" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" securetty_types \- файл конфигурации типа безопасного терминала (tty) SELinux . .SH "ОПИСАНИЕ" Файл .I securetty_types содержит список типов, связанных с типом безопасного tty, которые определены в политике для использования поддерживающими SELinux приложениями. .sp .BR selinux_securetty_types_path "(3) " вернёт путь активной политики к этому файлу. Файл типов securetty по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/securetty_types .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp .BR selinux_check_securetty_context "(3) выполняет чтение этого файла, чтобы определить, установлен ли в активной политике контекст для безопасного tty. " .sp Поддерживающие SELinux приложения, такие как .BR newrole "(1), используют эту информацию для проверки состояния tty. " . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле состоит из следующей записи: .sp .RS .I type .RS Одна или несколько записей типов, которые определены в политике для безопасных устройств tty. .RE .RE . .SH "ПРИМЕР" # ./contexts/securetty_types .br sysadm_tty_device_t .br user_tty_device_t .br staff_tty_device_t . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selinux_securetty_types_path "(3), " newrole "(1), " selinux_check_securetty_context "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/selabel_db.50100644 0000000 0000000 00000032141 13756670063 016204 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: KaiGai Kohei 2009 .TH "selabel_db" "5" "01 декабря 2011" "Security Enhanced Linux" "Документация API SELinux" .SH "ИМЯ" selabel_db \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов объектов RDBMS (реляционная СУБД) . .SH "ОБЗОР" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" . .SH "ОПИСАНИЕ" Внутренняя служба контекста базы данных сопоставляет имя и класс объекта с контекстами безопасности. Это действие позволяет найти правильный контекст для объектов базы данных при повторном проставлении меток для определённой базы данных. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. .sp \fIobject_name\fR должно быть полным именем, которое использует иерархию объектов базы данных. Например, таблица \fBpg_class\fR в базе данных \fBpostgres\fR и схема \fBpg_catalog\fR должны быть указаны следующим образом: .RS .B postgres.pg_catalog.pg_class .RE .sp В разделе \fBПРИМЕЧАНИЯ\fR доступны более подробные сведения о поддержке баз данных для иерархий пространства имён. .sp Для аргумента \fIobject_type\fR должно быть установлено одно из следующих значений: .RS .TP .B SELABEL_DB_DATABASE Аргумент .I object_name определяет имя самой базы данных, например, "postgres". .TP .B SELABEL_DB_SCHEMA Аргумент .I object_name определяет имя объекта схемы, например, "postgres.public". .TP .B SELABEL_DB_TABLE Аргумент .I object_name определяет имя объекта таблицы, например, "postgres.public.my_table" .TP .B SELABEL_DB_COLUMN Аргумент .I object_name определяет имя объекта столбца, например, "postgres.public.my_table.user_id" .TP .B SELABEL_DB_TUPLE Аргумент .I object_name определяет имя объекта таблицы, содержащей кортежи, для которых требуется повторно проставить метки, например, "postgresql.public.my_table". Следует учитывать, что нет способа идентифицировать отдельные объекты кортежа (за исключением условия WHERE для инструкций DML), потому что у них нет имён. .TP .B SELABEL_DB_PROCEDURE Аргумент .I object_name определяет имя объекта процедуры, например, "postgres.public.my_func". Следует учитывать, что поиск отдельных контекстов безопасности для процедур с одинаковыми именами, но разными аргументами не поддерживается. .TP .B SELABEL_DB_SEQUENCE Аргумент .I object_name определяет имя объекта последовательности, например, "postgres.public.my_seq". .TP .B SELABEL_DB_BLOB Аргумент .I object_name определяет имя большого объекта, например, "postgres.16308". Следует учитывать, что у большого объекта нет имени, поэтому он идентифицируется по значению соответствующего идентификатора. .TP .B SELABEL_DB_VIEW Аргумент .I object_name определяет имя объекта просмотра, например, "postgres.public.my_view". .TP .B SELABEL_DB_LANGUAGE Аргумент .I object_name определяет имя объекта языка, например, "postgres.public.tcl". .TP .B SELABEL_DB_EXCEPTION Аргумент .I object_name определяет имя объекта исключения. .TP .B SELABEL_DB_DATATYPE Аргумент .I object_name определяет имя объекта типа или домена, например, postgres.public.my_type. .RE .sp Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. .sp В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекста объекта базы данных. . .SH "ПАРАМЕТРЫ" Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: .RS .TP .B SELABEL_OPT_PATH Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекста базы данных. По умолчанию параметр пытается открыть файл спецификации, предназначенный для SE-PostgreSQL; если этот интерфейс используется другой реляционной СУБД, параметр должен явно объявить файл спецификации, предназначенный для такой реляционной СУБД (подробные сведения см. в разделе \fBФАЙЛЫ\fR). .RE . .SH "ФАЙЛЫ" То, какой файл контекстов базы данных будет использоваться для получения контекста, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов базы данных активной политики (возвращённое \fBselinux_sepgsql_context_path\fR(3)). В ином случае будет использоваться фактическое указанное значение \fBSELABEL_OPT_PATH\fR (этот вариант необходимо использовать для поддержки баз данных, отличных от SE-PostgreSQL). .sp Файл контекстов объекта базы данных по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/sepgsql_context .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp Записи внутри файла контекстов базы данных показаны в разделах \fBЗначения строки имени объекта\fR и \fBФОРМАТ ФАЙЛА\fR. . .SH "Значения строки имени объекта" Имена строк, назначенные аргументам \fIobject_type\fR, которые могут присутствовать в файле контекстов базы данных: .TS center, allbox, tab(@); lI lB lB l . object_type@Текстовое имя SELABEL_DB_DATABASE@db_database SELABEL_DB_SCHEMA@db_schema SELABEL_DB_VIEW@db_view SELABEL_DB_LANGUAGE@db_language SELABEL_DB_TABLE@db_table SELABEL_DB_COLUMN@db_column SELABEL_DB_TUPLE@db_tuple SELABEL_DB_PROCEDURE@db_procedure SELABEL_DB_SEQUENCE@db_sequence SELABEL_DB_BLOB@db_blob SELABEL_DB_EXCEPTION@db_exception SELABEL_DB_DATATYPE@db_datatype .TE . .SH "ФОРМАТ ФАЙЛА" Каждая строка внутри файла контекстов базы данных имеет следующий вид: .RS .I object_type object_name context .RE .sp Где: .RS .I object_type .RS Строковое представление типа объекта, показанное в разделе \fBЗначения строки имени объекта\fR. .RE .I object_name .RS Ключ, который используется для получения контекста на основе \fIobject_type\fR. .sp Запись может содержать подстановочные знаки '*' или '?' для выполнения сопоставления с дополнением или подстановкой. .sp Следует учитывать, что при использовании '*' важен порядок записей в файле. '*' в отдельном виде используется для того, чтобы обеспечить назначение резервного контекста по умолчанию, это должна быть последняя запись в блоке \fIobject_type\fR. .RE .I context .RS К объекту будет применён этот контекст безопасности. .RE .RE .sp Далее приведён пример для SE-PostgreSQL: .sp # ./contexts/sepgsql_contexts file .br # object_type object_name context .br db_database my_database system_u:object_r:sepgsql_db_t:s0 .br db_database * system_u:object_r:sepgsql_db_t:s0 .br db_schema *.* system_u:object_r:sepgsql_schema_t:s0 .br db_tuple row_low system_u:object_r:sepgsql_table_t:s0 .br db_tuple row_high system_u:object_r:sepgsql_table_t:s0:c1023 .br db_tuple *.*.* system_u:object_r:sepgsql_table_t:s0 . .SH "ПРИМЕЧАНИЯ" .IP "1." 4 Для целевой реляционной СУБД необходимо записать подходящий файл контекстов базы данных и использовать для его загрузки параметр \fBSELABEL_OPT_PATH\fR в \fBselabel_open\fR(3). .IP "2." 4 Иерархия пространства имён для объектов базы данных зависит от реляционной СУБД, но интерфейсы \fIselabel*\fR не предусматривают какой-либо особой поддержки иерархии пространства имён. .sp В иерархии пространства имён SE-PostgreSQL объектом верхнего уровня является база данных, объектом следующего уровня - схема. На следующем после объекта схемы уровне могут находиться другие типы объектов, например, таблицы и процедуры. Эта иерархия поддерживается следующим образом: .RS .RS .sp Если для таблицы "my_table" в схеме "public" внутри базы данных "postgres" требуется контекст безопасности, то параметрами \fBselabel_lookup\fR(3) для \fIobject_type\fR будет \fBSELABEL_DB_TABLE\fR, для \fIobject_name\fR - "postgres.public.my_table", контекст безопасности (если доступно) будет возвращён в \fIcontext\fR. .RE .RE .IP "3." 4 Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_sepgsql_context_path "(3), " freecon "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/selabel_file.50100644 0000000 0000000 00000034664 13756670063 016552 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_file" "5" "01 декабря 2011" "Security Enhanced Linux" "Документация API SELinux" .SH "ИМЯ" selabel_file \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов файлов . .SH "ОБЗОР" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" path ", int " mode ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" path ", int " mode ");" . .SH "ОПИСАНИЕ" Внутренняя служба контекстов файлов сопоставляет сочетания 'путь/режим' с контекстами безопасности. Это действие служит для нахождения правильного контекста для каждого файла при повторном проставлении меток в файловой системе. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. Тем не менее, далее приводится более подробное описание следующих значений \fIerrno\fR для внутренней службы контекстов файлов: .RS .TP .B ENOENT Не найден контекст, соответствующий \fIpath\fR и \fImode\fR, - это сообщение будет возвращено и в том случае, если серия файлов контекстов файлов имеет контекст \fB<>\fR относительно \fIpath\fR (см. раздел \fBФОРМАТ ФАЙЛА\fR). .RE .sp Аргумент \fIpath\fR должен быть установлен в полный путь к файлу, назначенный контекст которого проверяется. Аргумент \fImode\fR должен быть установлен в биты режима файла, как определено \fBlstat\fR(2). Аргумент \fImode\fR может быть нулевым, но в этом случае, возможно, не удастся установить полное соответствие. .sp Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. .sp В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекста файла. . .SH "ПАРАМЕТРЫ" Помимо глобальных параметров, описание которых приведено в .BR selabel_open (3), эта внутренняя служба распознаёт следующие параметры: .RS .TP .B SELABEL_OPT_PATH Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов файлов. Это значение также используется как базовое имя для определения имён локальных файлов настройки. .TP .B SELABEL_OPT_BASEONLY Отличное от null значение этого параметра означает, что любую локальную настройку сопоставления контекста файла следует игнорировать. .TP .B SELABEL_OPT_SUBSET Отличное от null значение этого параметра интерпретируется как префикс пути, например, "/etc". Будут загружены только те спецификации контекстов файлов, первый компонент которых совпадает с указанным префиксом. Это может ускорить выполнение поиска, но, возможно, не удастся найти путь, который не начинается с указанного префикса. Данная оптимизация поиска больше не требуется (и устарела), вместо неё используется .I file_contexts.bin. .RE . .SH "ФАЙЛЫ" То, какие файлы контекстов файлов используются для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если это \fINULL\fR, то \fBSELABEL_OPT_PATH\fR по умолчанию примет значение расположения контекстов файлов активной политики (которое возвращает \fBselinux_file_context_path\fR(3)), в ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. .sp Если параметр \fBSELABEL_OPT_BASEONLY\fR задан, будут обрабатываться следующие файлы: .RS .IP "1." 4 Обязательный файл контекстов файлов - это либо полное имя файла из \fISELABEL_OPT_PATH.value\fR, либо (если \fINULL\fR) путь, который возвращает \fBselinux_file_context_path\fR(3). .IP "2." 4 Необязательные файлы для замены имён (файл для локального использования и файл для использования с дистрибутивами), которые присваивают псевдонимы пути для 'находящейся в памяти' версии файла контекстов файлов. .br Эти файлы имеют то же имя, что и у обязательного файла контекстов файлов, и расширения \fI.subs\fR и \fI.subs_dist\fR. .RE .sp Если параметр \fBSELABEL_OPT_BASEONLY\fR не задан, будут обработаны следующие файлы: .RS .IP "1." 4 Обязательный файл контекстов файлов, который является либо полным именем файла из \fISELABEL_OPT_PATH.value\fR, либо (если \fINULL\fR) путём, который возвращает \fBselinux_file_context_path\fR(3). .IP "2." 4 Необязательный файл локальной настройки, имеющий то же имя, что и обязательный файл контекстов файлов, и расширение \fI.local\fR. .br \fBselinux_file_context_local_path\fR(3) вернёт путь по умолчанию к этому файлу. .IP "3." 4 Необязательный файл настройки домашнего каталога пользователя, имеющий то же имя, что и обязательный файл контекстов файлов, и расширение \fI.homedirs\fR. .br \fBselinux_file_context_homedir_path\fR(3) вернёт путь по умолчанию к этому файлу. .IP "4." 4 Необязательные файлы для замены имён (файл для локального использования и файл для использования с дистрибутивами), которые присваивают псевдонимы пути для 'находящейся в памяти' версии файла контекстов файлов (и \fI.local\fR и/или \fI.homedirs\fR, если они имеются). Эти файлы имеют то же имя, что и обязательный файл контекстов файлов, и расширения \fI.subs\fR и \fI.subs_dist\fR. .br \fBselinux_file_context_subs_path\fR(3) и \fBselinux_file_context_subs_dist_path\fR(3) вернут пути по умолчанию к этим файлам. .RE .sp По умолчанию серия файлов контекстов файлов: .RS 6 .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.local .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.homedirs .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs .br .I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs_dist .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp Обязательным является только файл \fIfile_contexts\fR, все остальные являются необязательными. .sp Записи внутри серии файлов контекстов файлов показаны в разделе \fBФОРМАТ ФАЙЛА\fR. . .SH "ФОРМАТ ФАЙЛА" .sp .SH "Формат контекстов файлов" .sp Каждая строка внутри \fIfile_contexts\fR и двух файлов настройки (\fI.local\fR и \fI.homedirs\fR) имеет следующий вид: .sp .RS .I pathname [file_type] context .RE .sp Где: .br .RS .I pathname .RS Определяющая имя пути запись, которая может быть в виде регулярного выражения. .RE .I file_type .RS Необязательный тип файла, который состоит из: .RS \fI\-b\fR - устройство блочного ввода-вывода \fI\-c\fR - устройство символьного ввода-вывода .br \fI\-d\fR - каталог \fI\-p\fR - именованный канал .br \fI\-l\fR - символическая ссылка \fI\-s\fR - сокет .br \fI\-\-\fR - обычный файл .RE .RE .I context .RS Запись может быть одним из следующих: .RS .IP "a." 4 Контекст безопасности, который будет назначен этому файлу (то есть возвращён как \fIcontext\fR). .IP "b." 4 Значение \fB<>\fR можно использовать, чтобы указать, что для соответствующих файлов не следует повторно проставлять метки, а также при этом значении \fBselabel_lookup\fR(3) вернёт \-1 при установке \fIerrno\fR в \fBENOENT\fR. .RE .RE .RE .sp Пример: .RS # ./contexts/files/file_contexts .br # pathname file_type context .br /.* system_u:object_r:default_t:s0 .br /[^/]+ \-\- system_u:object_r:etc_runtime_t:s0 .br /tmp/.* <> .RE .sp .SH "Формат файла подстановки" .sp Каждая строка внутри файлов подстановки (\fI.subs\fR и \fI.subs_dist\fR) имеет вид: .RS .I subs_pathname pathname .RE .sp Где: .RS .I pathname .RS Путь, который соответствует записи в одном или нескольких файлах конфигурации политики контекстов файлов. .RE .I subs_pathname .RS Путь, который станет псевдонимом имени пути (считается равнозначным при поиске). .RE .RE .sp Пример: .RS # ./contexts/files/file_contexts.subs .br # pathname subs_pathname .br /myweb /var/www .br /myspool /var/spool/mail .sp Пример выше: когда в \fBselabel_lookup\fR(3) передаётся путь \fI/myweb/index.html\fR, функция заменяет компонент \fI/myweb\fR на \fI/var/www\fR, поэтому будет использоваться следующий путь: .sp .RS .I /var/www/index.html .RE .RE . .SH "ПРИМЕЧАНИЯ" .IP "1." 4 Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. .IP "2." 4 Если серия файлов контекстов файлов содержит много записей, \fBselabel_open\fR(3) может медленно выполнять чтение в файлах и (если это запрошено) проверку записей. .IP "3." 4 В некоторых версиях SELinux также может присутствовать файл \fIfile_contexts.template\fR, но он устарел. .br Файл шаблона имеет тот же формат, что и файл \fIfile_contexts\fR, а также может содержать ключевые слова \fBHOME_ROOT\fR, \fBHOME_DIR\fR, \fBROLE\fR и \fBUSER\fR. Эта функциональность была перемещена в хранилище политик и управляется \fBsemodule\fR(8) и \fBgenhomedircon\fR(8). . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_file_context_path "(3), " freecon "(3), " selinux_config "(5), " lstat "(2), "selinux_file_context_subs_path "(3), " selinux_file_context_subs_dist_path "(3), " selinux_file_context_homedir_path "(3), "selinux_file_context_local_path "(3), " semodule "(8), " genhomedircon "(8) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/selabel_media.50100644 0000000 0000000 00000012571 13756670063 016703 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_media" "5" "29 ноября 2011" "Security Enhanced Linux" "Документация API SELinux" .SH "ИМЯ" selabel_media \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов носителей . .SH "ОБЗОР" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" device_name ", int " unused ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" device_name ", int " unused ");" . .SH "ОПИСАНИЕ" Внутренняя служба контекстов носителей сопоставляет имена устройств мультимедиа, например, "cdrom" или "floppy", с контекстами безопасности. Это действие служит для нахождения правильного контекста для установки контекстных подключений к этим устройствам. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. .sp Аргумент поиска целого числа в настоящее время не используется, для него следует указать равное нулю значение. .sp Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). .sp .BR selabel_lookup_raw (3) работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. .sp В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекстов носителей. . .SH "ПАРАМЕТРЫ" Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: .TP .B SELABEL_OPT_PATH Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов носителей \fImedia\fR. . .SH "ФАЙЛЫ" То, какой файл контекстов носителей будет использоваться для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\FR(3). Если это \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов носителей активной политики (возвращённое \fBselinux_media_context_path\fR(3)). В ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. .sp Файл контекстов носителей по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/files/media .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Каждая строка внутри файла \fImedia\fR имеет следующий вид: .RS .I device_name context .RE .sp Где: .RS .I device_name .RS Идентификатор носителя (например, cdrom, floppy, disk и usb). .RE .I context .RS Контекст, который следует использовать для проставления метки устройства. .RE .RE .sp Пример: .RS # contexts/files/media .br cdrom system_u:object_r:removable_device_t .br floppy system_u:object_r:removable_device_t .br disk system_u:object_r:fixed_disk_device_t . .SH "ПРИМЕЧАНИЯ" Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_media_context_path "(3), " freecon "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/selabel_x.50100644 0000000 0000000 00000025225 13756670063 016073 0ustar000000000 0000000 .\" Hey Emacs! This file is -*- nroff -*- source. .\" .\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 .TH "selabel_x" "5" "29 ноября 2011" "Security Enhanced Linux" "Документация API SELinux" .SH "ИМЯ" selabel_x \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов оконной системы X Window System. Эта внутренняя служба также используется для определения контекста по умолчанию, который следует присвоить подключённым удалённо клиентам X . .SH "ОБЗОР" .B #include .sp .BI "int selabel_lookup(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" .in .sp .BI "int selabel_lookup_raw(struct selabel_handle *" hnd , .in +\w'int selabel_lookup('u .BI "char **" context , .br .BI "const char *" object_name ", int " object_type ");" . .SH "ОПИСАНИЕ" Внутренняя служба контекстов X сопоставляет имена объектов X Window System с контекстами безопасности. Это действие служит для нахождения правильного контекста для объектов X Window System, значимость и/или семантика использования которых в основном определяются именем. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). .br \fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. .sp Эта внутренняя служба также используется для определения контекста по умолчанию, который следует назначить для подключённых удалённо клиентов X. .sp Для аргумента \fIobject_type\fR необходимо установить одно из следующих значений: .RS .TP .B SELABEL_X_PROP Аргумент .I object_name указывает имя свойства окна, например, "WM_NAME". .TP .B SELABEL_X_SELN Аргумент .I object_name указывает имя выделения, например, "PRIMARY". .TP .B SELABEL_X_EXT Аргумент .I object_name указывает имя расширения протокола, например, "RENDER". .TP .B SELABEL_X_EVENT Аргумент .I object_name указывает имя типа события, например, "X11:ButtonPress". .TP .B SELABEL_X_CLIENT Аргумент .I object_name игнорируется, но его значением необходимо установить либо \fI*\fR (звёздочка, 'подстановочный знак': будет выбрана запись по умолчанию), либо конкретную запись, такую как "remote" в файле контекстов X, как показано в разделе \fBПРИМЕР\fR. В этом случае будет возвращён контекст по умолчанию, который следует присвоить удалённым клиентам X. .TP .B SELABEL_X_POLYPROP Работает аналогично .BR SELABEL_X_PROP , но проверяет, было ли свойство отмечено как многоэкземплярное. См. \fBПРИМЕЧАНИЯ\fR далее. .TP .B SELABEL_X_POLYSELN Аналогично .BR SELABEL_X_SELN , но проверяет, было ли выделение отмечено как многоэкземплярное. См. \fBПРИМЕЧАНИЯ\fR далее. .RE .sp Все сообщения, созданные \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). .sp .B selabel_lookup_raw работает аналогично \fBselabel_lookup\fR, но не выполняет преобразование контекста. .sp В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекстов объектов Х. . .SH "ПАРАМЕТРЫ" Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: .RS .TP .B SELABEL_OPT_PATH Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов Х (подробные сведения см. в разделе \fBФАЙЛЫ\fR). .RE . .SH "ФАЙЛЫ" То, какой файл контекста Х будет использоваться для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов Х активной политики (возвращённое \fBselinux_x_context_path\fR(3)). В ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. .sp Файл контекстов объектов Х по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/x_contexts .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp Записи, находящиеся внутри файла контекстов X, показаны в разделах \fBЗначения строки имени объекта\fR и \fBФОРМАТ ФАЙЛА\fR. . .SH "Значения строки имени объекта" Имена строк, назначенные аргументам \fIobject_type\fR, которые могут присутствовать в файле контекстов X: .TS center, allbox, tab(@); lI lB lB l . object_type@Текстовое имя SELABEL_X_PROP@property SELABEL_X_SELN@selection SELABEL_X_EXT@extension SELABEL_X_EVENT@event SELABEL_X_CLIENT@client SELABEL_X_POLYPROP@poly_property SELABEL_X_POLYSELN@poly_selection .TE . .SH "ФОРМАТ ФАЙЛА" Каждая строка внутри файла контекстов X имеет следующий вид: .RS .I object_type object_name context .RE .sp Где: .RS .I object_type .RS Это строковое представление типа объекта, показанное в разделе \fBЗначения строки имени объекта\fR. Несколько строк с одной и той же строкой \fIobject_type\fR сформируют блок записей (каждая со своей строкой \fIobject_name\fR). .RE .I object_name .RS Это имена объектов конкретного ресурса сервера X, например, \fBPRIMARY\fR, \fBCUT_BUFFER0\fR и т.д. Обычно они определены в исходном коде сервера X (\fIprotocol.txt\fR и \fIBuiltInAtoms\fR в каталоге dix исходного пакета xorg\-server). Запись может содержать подстановочные знаки '*' или '?' для выполнения сопоставления с дополнением или подстановкой. Следует учитывать, что при использовании '*' важен порядок записей в файле. '*' в отдельном виде используется для того, чтобы обеспечить назначение резервного контекста по умолчанию, это должна быть последняя запись в блоке \fIobject_type\fR. .RE .I context .RS Контекст безопасности, который будет применён к объекту. .RE .RE .sp Пример 1: .sp .nf # object_type object_name context selection PRIMARY system_u:object_r:clipboard_xselection_t:s0 selection * system_u:object_r:xselection_t:s0 .fi .sp Пример 2 - этот пример показывает, как можно настроить запись клиента таким образом, чтобы она всегда находилась: .sp .nf # object_type object_name context client * system_u:object_r:remote_t:s0 .fi . .SH "ПРИМЕЧАНИЯ" .IP "1." 4 Свойства и выделения отмечаются как многоэкземплярные или нет. Для этих типов имён параметр "POLY" выполняет поиск только имён, которые отмечены как многоэкземплярные, в то время как другой параметр выполняет поиск только имён, которые отмечены как не многоэкземплярные. Пользователям этого интерфейса следует проверить оба сопоставления и затем (необязательно) действовать на основе полученного результата (например, сделать объект многоэкземплярным). .IP "2." 4 Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_x_context_path "(3), " freecon "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/sepgsql_contexts.50100644 0000000 0000000 00000000026 13756670063 017532 0ustar000000000 0000000 .so man5/selabel_db.5 libselinux/man/ru/man5/service_seusers.50100644 0000000 0000000 00000005362 13756670063 017346 0ustar000000000 0000000 .TH "service_seusers" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" service_seusers \- файлы конфигурации сопоставления пользователей и служб GNU/Linux с пользователями SELinux . .SH "ОПИСАНИЕ" Это необязательные файлы, которые позволяют службам определять пользователя SELinux при аутентификации через поддерживающие SELinux приложения для входа, например, .BR PAM "(8). " .sp Для каждого имени пользователя GNU/Linux имеется один файл, который потребуется для запуска службы с определённым именем пользователя SELinux. .sp Путь к каждому файлу конфигурации формируется путём, который был возвращён .BR selinux_policy_root "(3), с добавлением " .IR /logins/username в конце (где \fIusername\fR - это файл, представляющий имя пользователя GNU/Linux). Каталог служб по умолчанию расположен по следующему адресу: .RS .I /etc/selinux/{SELINUXTYPE}/logins .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp .BR getseuser "(3) выполняет чтение этого файла для сопоставления служб с пользователем SELinux. " . .SH "ФОРМАТ ФАЙЛА" Каждая строка внутри файла \fIusername\fR имеет следующий формат, каждый компонент отделяется двоеточием: .RS .IB service : seuser \fR[\fB:\fIrange\fR] .RE .sp Где: .RS .I service .RS Имя службы, которая используется приложением. .RE .I seuser .RS Имя пользователя SELinux. .RE .I range .RS Диапазон для политики MCS/MLS. .RE .RE . .SH "ПРИМЕРЫ" Пример 1 - для пользователя 'root': .RS # ./logins/root .br ipa:user_u:s0 .br this_service:unconfined_u:s0 .RE .sp Пример 2 - для пользователя GNU/Linux 'rch': .RS # ./logins/rch .br ipa:unconfined_u:s0 .br that_service:unconfined_u:s0 .RE . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " PAM "(8), " selinux_policy_root "(3), " getseuser "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/seusers.50100644 0000000 0000000 00000005205 13756670063 015622 0ustar000000000 0000000 .TH "seusers" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" seusers \- файл конфигурации сопоставления пользователей GNU/Linux с пользователями SELinux . .SH "ОПИСАНИЕ" Файл .I seusers содержит список сопоставления пользователей GNU/Linux с пользователями SELinux, который используется поддерживающими SELinux приложениями для входа, например, \fBPAM\fR(8). .sp .BR selinux_usersconf_path "(3) " вернёт путь активной политики к этому файлу. Файл сопоставления пользователей SELinux по умолчанию находится по следующему адресу: .RS .I /etc/selinux/{SELINUXTYPE}/seusers .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp .BR getseuserbyname "(3) выполняет чтение этого файла для сопоставления пользователя или группы GNU/Linux с пользователем SELinux. " . .SH "ФОРМАТ ФАЙЛА" Каждая строка файла конфигурации .I seusers состоит из следующих компонентов: .sp .RS \fR[\fB%\fIgroup_id\fR]|[\fIuser_id\fR]\fB:\fIseuser_id\fR[\fB:\fIrange\fR] .RE .sp Где: .RS \fIgroup_id\fR|\fIuser_id .RS \fRИдентификатор пользователя GNU/Linux или (если предваряется символом процентного значения (\fB%\fR)) идентификатор группы GNU/Linux. .br При необходимости в качестве резервной записи можно предоставить необязательную запись, установленную в \fB__default__\fR. .RE .I seuser_id .RS Идентификатор пользователя SELinux. .RE .I range .RS Необязательный уровень или диапазон для политики MLS/MCS. .RE .RE . .SH "ПРИМЕР" # ./seusers .br system_u:system_u:s0\-s15:c0.c255 .br root:root:s0\-s15:c0.c255 .br fred:user_u:s0 .br __default__:user_u:s0 .br %user_group:user_u:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " PAM "(8), " selinux_usersconf_path "(3), " getseuserbyname "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/user_contexts.50100644 0000000 0000000 00000007522 13756670063 017042 0ustar000000000 0000000 .TH "user_contexts" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" user_contexts \- файлы конфигурации SELinux-контекстов пользователей SELinux . .SH "ОПИСАНИЕ" Эти необязательные файлы конфигурации контекстов пользователей содержат записи, которые позволяют поддерживающим SELinux приложениям для входа, например, .BR PAM (8) (запущенным в своих собственных контекстах процессов), определять контекст, в котором должен запускаться сеанс пользователя. .sp Обычно поддерживающие SELinux приложения для входа используют одну или несколько следующих функций libselinux, которые выполняют чтение этих файлов по пути активной политики: .RS .BR get_default_context (3) .br .BR get_ordered_context_list (3) .br .BR get_ordered_context_list_with_level (3) .br .BR get_default_context_with_level (3) .br .BR get_default_context_with_role (3) .br .BR get_default_context_with_rolelevel (3) .br .BR query_user_context (3) .br .BR manual_user_enter_context (3) .RE .sp Для каждого пользователя SELinux можно настроить только один файл. Путь к файлу формируется с помощью пути, возвращённого .BR \%selinux_user_contexts_path (3) для активной политики, с добавлением в конце имени пользователя SELinux, например: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/users/unconfined_u .br .I /etc/selinux/{SELINUXTYPE}/contexts/users/xguest_u .RE .sp Где \fI{SELINUXTYPE}\fR - запись файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). .sp Эти файлы содержат информацию о контексте в соответствии с описанием в разделе .B ФОРМАТ ФАЙЛА. . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле конфигурации контекста пользователя состоит из следующих компонентов: .RS .I login_process user_login_process .RE .sp Где: .RS .I login_process .RS Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа. .RE .I user_login_process .RS Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа пользователя. .RE .RE . .SH "ПРИМЕР" # Пример для xguest_u в /etc/selinux/targeted/contexts/users/xguest_u .br system_r:crond_t:s0 xguest_r:xguest_t:s0 .br system_r:initrc_t:s0 xguest_r:xguest_t:s0 .br system_r:local_login_t:s0 xguest_r:xguest_t:s0 .br system_r:remote_login_t:s0 xguest_r:xguest_t:s0 .br system_r:sshd_t:s0 xguest_r:xguest_t:s0 .br system_r:xdm_t:s0 xguest_r:xguest_t:s0 .br xguest_r:xguest_t:s0 xguest_r:xguest_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " selinux_user_contexts_path "(3), " PAM "(8), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/virtual_domain_context.50100644 0000000 0000000 00000003572 13756670063 020717 0ustar000000000 0000000 .TH "virtual_domain_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" virtual_domain_context \- файл конфигурации SELinux-контекста домена виртуальной машины . .SH "ОПИСАНИЕ" Файл .I virtual_domain_context содержит список контекстов доменов, которые доступны для использования поддерживающему SELinux API виртуализации libvirt (см. \fBlibvirtd\fR(8)). .sp .BR selinux_virtual_domain_context_path "(3) " вернёт путь активной политики к этому файлу. Файл контекстов виртуальных доменов по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/virtual_domain_context .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле состоит из записи следующего вида: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Где: .RS .I user role type range .RS Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые могут использоваться в качестве контекста виртуального домена. .RE .RE . .SH "ПРИМЕР" # ./contexts/virtual_domain_context .br system_u:object_r:svirt_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " libvirtd "(8), " selinux_virtual_domain_context_path "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/virtual_image_context.50100644 0000000 0000000 00000003576 13756670063 020536 0ustar000000000 0000000 .TH "virtual_image_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" .SH "ИМЯ" virtual_image_context \- файл конфигурации SELinux-контекста образа виртуальной машины . .SH "ОПИСАНИЕ" Файл .I virtual_image_context содержит список контекстов образов для использования поддерживающим SELinux API виртуализации libvirt (см. \fBlibvirtd\fR(8)). .sp .BR selinux_virtual_image_context_path "(3) " вернёт путь активной политики к этому файлу. Файл контекстов виртуальных образов по умолчанию: .RS .I /etc/selinux/{SELINUXTYPE}/contexts/virtual_image_context .RE .sp Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). . .SH "ФОРМАТ ФАЙЛА" Каждая строка в файле состоит из записи следующего вида: .RS .IB user : role : type \fR[\fB:\fIrange\fR] .RE .sp Где: .RS .I user role type range .RS Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые могут использоваться в качестве контекста виртуального образа. .RE .RE . .SH "ПРИМЕР" # ./contexts/virtual_image_context .br system_u:object_r:svirt_image_t:s0 .br system_u:object_r:svirt_content_t:s0 . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR selinux "(8), " libvirtd "(8), " selinux_virtual_image_context_path "(3), " selinux_config "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man5/x_contexts.50100644 0000000 0000000 00000000025 13756670063 016322 0ustar000000000 0000000 .so man5/selabel_x.5 libselinux/man/ru/man8/0040755 0000000 0000000 00000000000 13756670063 014047 5ustar000000000 0000000 libselinux/man/ru/man8/avcstat.80100644 0000000 0000000 00000002542 13756670063 015605 0ustar000000000 0000000 .TH "avcstat" "8" "18 ноября 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" avcstat \- показать статистику AVC (Access Vector Cache, кэш вектора доступа) SELinux . .SH "ОБЗОР" .B avcstat .RB [ \-c ] .RB [ \-f .IR status_file ] .RI [ interval ] . .SH "ОПИСАНИЕ" Показать статистику AVC SELinux. Если указан параметр .I interval , программа будет выполняться циклами, показывая обновлённую статистику каждые .I interval секунд. По умолчанию показываются относительные значения. . .SH ПАРАМЕТРЫ .TP .B \-c Показать совокупные значения. .TP .B \-f Указывает расположение файла статистики AVC, по умолчанию это .IR /sys/fs/selinux/avc/cache_stats . . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8) . .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Программа была написана James Morris . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/booleans.80100644 0000000 0000000 00000007354 13756670063 015750 0ustar000000000 0000000 .TH "booleans" "8" "11 августа 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" booleans \- логические переключатели политики позволяют настраивать политику SELinux в среде выполнения . .SH "ОПИСАНИЕ" Эта страница руководства описывает логические переключатели политики SELinux. .BR Политика SELinux может включать условные правила, которое включены или отключены в зависимости от текущих значений набора логических переключателей политики. Эти логические переключатели политики позволяют изменять политику безопасности в среде выполнения без загрузки новой политики. Например, логический переключатель httpd_enable_cgi (если он включён) позволяет управляющей программе httpd запускать сценарии cgi. Если администратору требуется запретить исполнение сценариев cgi, можно просто установить соответствующее значение этого переключателя. Политика определяет значение по умолчанию для каждого логического переключателя, обычно это false. Эти значения по умолчанию можно переопределить через локальные параметры, созданные с помощью утилиты .BR setsebool (8) , используя .B \-P для сохранения параметра после перезагрузок. Средство .B system\-config\-securitylevel предоставляет графический интерфейс для изменения параметров. Программа .BR load_policy (8) по умолчанию сохранит текущие параметры логических переключателей после перезагрузки политики по умолчанию. При необходимости также можно сбросить значения логических переключателей на их значения по умолчанию при загрузке, для этого используется параметр .B \-b. Для получения и вывода списка логических значений служит утилита .BR getsebool (8) с параметром .B \-a. Логические значения также можно изменить во время выполнения с помощью утилиты .BR setsebool (8) или утилиты .BR togglesebool (8). По умолчанию эти утилиты изменяют только текущее логическое значение и не влияют на постоянные параметры, если в setsebool не используется параметр .B \-P. . .SH "СМОТРИТЕ ТАКЖЕ" .BR getsebool (8), .BR setsebool (8), .BR selinux (8), .BR togglesebool (8) . .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Поддержка условной политики SELinux была разработана Tresys Technology. Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/getenforce.80100644 0000000 0000000 00000001304 13756670063 016254 0ustar000000000 0000000 .TH "getenforce" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" getenforce \- получить текущий режим SELinux . .SH "ОБЗОР" .B getenforce . .SH "ОПИСАНИЕ" .B getenforce сообщает, в каком режиме работает SELinux (принудительный, разрешительный, отключённый). . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR setenforce (8), .BR selinuxenabled (8) . .SH АВТОРЫ Dan Walsh, . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/getsebool.80100644 0000000 0000000 00000004301 13756670063 016116 0ustar000000000 0000000 .TH "getsebool" "8" "11 августа 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" getsebool \- получить логические значения SELinux . .SH "ОБЗОР" .B getsebool .RB [ \-a ] .RI [ boolean ] . .SH "ОПИСАНИЕ" .B getsebool сообщает, где включён или отключён конкретный логический переключатель или все логические переключатели SELinux. В некоторых ситуациях для логического переключателя может существовать ожидающее изменение (переход из одного состояние в другое) - getsebool сообщит об этом. Ожидающее значение - то значение, которое будет применено при следующей фиксации логического переключателя. Установка значений логических переключателей выполняется в два этапа; сначала изменяется ожидающее значение, а затем логические переключатели фиксируются, в результате чего их активные значения заменяются ожидающими значениями. Это позволяет изменить группу логических переключателей за одну транзацию, задав все необходимые ожидающие значения и затем одновременно зафиксировав их. . .SH ПАРАМЕТРЫ .TP .B \-a Показать все логические переключатели SELinux. . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR setsebool (8), .BR booleans (8) . .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Программа была написана Tresys Technology. Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/matchpathcon.80100644 0000000 0000000 00000005057 13756670063 016615 0ustar000000000 0000000 .TH "matchpathcon" "8" "21 апреля 2005" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" matchpathcon \- получить текущий контекст безопасности SELinux для указанного пути из конфигурации контекстов файлов . .SH "ОБЗОР" .B matchpathcon .RB [ \-V ] .RB [ \-N ] .RB [ \-n ] .RB [ \-m .IR type ] .RB [ \-f .IR file_contexts_file ] .RB [ \-p .IR prefix ] .RB [ \-P .IR policy_root_path ] .I filepath... . .SH "ОПИСАНИЕ" .BR matchpathcon опрашивает системную политику и выводит контекст безопасности по умолчанию, связанный с путём к файлу. .B Примечание: Одинаковые пути могут иметь разные контексты безопасности в зависимости от типа файла (обычный файл, каталог, файл связи, файл знаков ...). .B matchpathcon также будет учитывать тип файла при определении контекста безопасности по умолчанию (если файл существует). Если файл не существует, сопоставление по типу файла не будет выполнено. . .SH ПАРАМЕТРЫ .TP .BI \-m " type" Принудительно указать тип файла для поиска. Действительные типы: .BR file ", " dir ", "pipe ", " chr_file ", " blk_file ", " .BR lnk_file ", " sock_file . .TP .B \-n Не показывать путь. .TP .B \-N Не использовать преобразования. .TP .BI \-f " file_context_file" Использовать альтернативный файл file_context .TP .BI \-p " prefix" Использовать префикс для ускорения преобразований .TP .BI \-P " policy_root_path" Использовать альтернативный корневой путь к политике .TP .B \-V Проверить контекст файла на диске на соответствие параметрам по умолчанию . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux "(8), " .BR matchpathcon (3) . .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/sefcontext_compile.80100644 0000000 0000000 00000004666 13756670063 020043 0ustar000000000 0000000 .TH "sefcontext_compile" "8" "12 августа 2015" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" sefcontext_compile \- скомпилировать файлы регулярных выражений контекстов файлов . .SH "ОБЗОР" .B sefcontext_compile .RB [ \-o .IR outputfile ] .RB [ \-p .IR policyfile ] .I inputfile . .SH "ОПИСАНИЕ" .B sefcontext_compile используется для компиляции регулярных выражений контекстов файлов в формат .BR pcre (3). .sp Скомпилированный файл используется функциями проставления меток файлов libselinux. .sp По умолчанию .B sefcontext_compile записывает скомпилированный файл pcre с суффиксом .B .bin в конце (например, \fIinputfile\fB.bin\fR). .SH ПАРАМЕТРЫ .TP .B \-o Указать .I outputfile - должно быть полным именем файла, так как суффикс .B .bin не добавляется автоматически. .TP .B \-p Указать двоичный .I policyfile для использования при проверке записей контекста в .I inputfile .br Если найден недействительный контекст, запись файла в формате pcre не будет выполнена и появится сообщение об ошибке. .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" При ошибке возвращается -1. При успешном завершении возвращается 0. .SH "ПРИМЕРЫ" .B Пример 1: .br sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts .sp В результате создаётся следующий файл: .RS /etc/selinux/targeted/contexts/files/file_contexts.bin .RE .sp .B Пример 2: .br sefcontext_compile -o new_fc.bin /etc/selinux/targeted/contexts/files/file_contexts .sp В результате в текущем рабочем каталоге создаётся следующий файл: .RS new_fc.bin .RE . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR semanage (8) . .SH АВТОРЫ Dan Walsh, . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/selinux.80100644 0000000 0000000 00000020777 13756670063 015641 0ustar000000000 0000000 .TH "selinux" "8" "29 апреля 2005" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" SELinux \- Linux с улучшенной безопасностью от NSA (SELinux) . .SH "ОПИСАНИЕ" Linux с улучшенной безопасностью от NSA - это реализация гибкой архитектуры мандатного управления доступом в операционной системе Linux. Архитектура SELinux предоставляет общую поддержку использования различных видов политик мандатного управления доступом, включая основанные на концепциях Type Enforcement® (принудительное присвоение типов), Role-Based Access Control (управление доступом на основе ролей) и Multi-Level Security (многоуровневая безопасность). Дополнительная информация и техническая документация по SELinux доступна по адресу http://www.nsa.gov/research/selinux. Файл конфигурации .I /etc/selinux/config позволяет управлять включением и отключением SELinux и, если SELinux включён, устанавливать режим его работы - разрешительный или принудительный. Переменной .B SELINUX можно задать значение отключённой, разрешительной или принудительной, чтобы выбрать один из этих вариантов. Если выбрать отключение режима, код ядра и приложения SELinux будет полностью отключён, система будет работать без какой-либо защиты SELinux. При установке разрешительного режима код SELinux включён, но не выполняет отказы в доступе, а только журналирует те действия, которые были бы запрещены при принудительном режиме. При установке принудительного режима код SELinux включён, выполняет отказы в доступе и журналирует соответствующие попытки доступа. Набор отказов в доступе в разрешительном режиме может отличаться от этого набора в принудительном режиме как по причине того, что принудительный режим предотвращает дальнейшее выполнение операции после первого отказа, так и из-за того, что после получения отказа в доступе часть кода приложения вернётся к работе в менее привилегированном режиме. Файл конфигурации .I /etc/selinux/config также управляет тем, какая политика активна в системе. SELinux позволяет установить в системе несколько политик, но одновременно можно использовать только одну из них. В настоящее время имеется несколько видов политики SELinux, например, целевая политика (targeted), политика многоуровневой безопасности (mls). Целевая политика позволяет большинству процессов пользователя выполняться без ограничений, помещая в отдельные домены безопасности, ограниченные политикой, только отдельные службы. Например, процессы пользователя выполняются в никак не ограниченном домене, в то время как именованная управляющая программа или управляющая программа apache будет выполняться в отдельном специально настроенном домене. Если используется политика MLS (Multi-Level Security), все процессы будут разделены по детально настроенным доменам безопасности и ограничены политикой. MLS также поддерживает модель Белла — Лападулы, в которой процессы ограничиваются не только по типу, но и по уровню данных. Чтобы определить, какая политика будет выполняться, следует установить переменную среды .B SELINUXTYPE в .IR /etc/selinux/config . Чтобы применить к системе изменение типа политики, необходимо перезагрузить систему и, возможно, повторно проставить метки. В каталогах .I /etc/selinux/{SELINUXTYPE}/ необходимо установить для каждой такой политики соответствующую конфигурацию. Дальнейшую настройку отдельной политики SELinux можно выполнить с помощью набора настраиваемых при компиляции параметров и набора логических переключателей среды выполнения политики. .B \%system\-config\-selinux позволяет настроить эти логические переключатели и настраиваемые параметры. Многие домены, которые защищены SELinux, также содержат man-страницы SELinux с информацией о настройке соответствующей политики. . .SH "ПРОСТАВЛЕНИЕ МЕТОК ДЛЯ ФАЙЛОВ" Всем файлам, каталогам, устройствам ... назначены контексты безопасности/метки. Эти контексты хранятся в расширенных атрибутах файловой системы. Проблемы с SELinux часто возникают из-за неправильного проставления меток в файловой системе. Это может быть вызвано загрузкой компьютера с ядром, отличным от SELinux. Появление сообщения об ошибке, содержащего file_t, обычно означает серьёзную проблему с проставлением меток в файловой системе. Лучшим способом повторного проставления меток в файловой системе является создание файла флага .I /.autorelabel и последующая перезагрузка. .BR system\-config\-selinux также имеет эту функциональность. Кроме того, для повторного проставления меток для файлов можно использовать команды .BR restorecon / fixfiles. . .SH ФАЙЛЫ .I /etc/selinux/config . .SH "СМОТРИТЕ ТАКЖЕ" .ad l .nh .BR booleans (8), .BR setsebool (8), .BR sepolicy (8), .BR system-config-selinux (8), .BR togglesebool (8), .BR restorecon (8), .BR fixfiles (8), .BR setfiles (8), .BR semanage (8), .BR sepolicy (8) Для каждой ограниченной службы в системе имеется man-cтраница следующего формата: .br .BR _selinux (8) Например, для службы httpd имеется страница .BR httpd_selinux (8). .B man -k selinux Выведет список всех man-страниц SELinux. .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/selinuxenabled.80100644 0000000 0000000 00000001601 13756670063 017135 0ustar000000000 0000000 .TH "selinuxenabled" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" selinuxenabled \- утилита для использования внутри сценариев оболочки, которая позволяет определить, включён ли selinux . .SH "ОБЗОР" .B selinuxenabled . .SH "ОПИСАНИЕ" Показывает, включён или отключён SELinux. . .SH "СОСТОЯНИЕ ВЫХОДА" Выход с состоянием 0, если SELinux включён, и 1, если он отключён. . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR setenforce (8), .BR getenforce (8) . .SH АВТОРЫ Dan Walsh, . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/selinuxexeccon.80100644 0000000 0000000 00000002064 13756670063 017173 0ustar000000000 0000000 .TH "selinuxexeccon" "8" "14 мая 2011" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" selinuxexeccon \- сообщить контекст SELinux, который используется для этого исполняемого файла . .SH "ОБЗОР" .B selinuxexeccon .I command .RI [ fromcon ] . .SH "ОПИСАНИЕ" .B selinuxexeccon сообщает контекст SELinux для указанной команды из указанного контекста или текущего контекста. . .SH ПРИМЕР .nf # selinuxexeccon /usr/bin/passwd staff_u:staff_r:passwd_t:s0-s0:c0.c1023 # selinuxexeccon /usr/sbin/sendmail system_u:system_r:httpd_t:s0 system_u:system_r:system_mail_t:s0 .fi . .SH "СМОТРИТЕ ТАКЖЕ" .BR secon (8) . .SH АВТОРЫ Эта страница руководства была написана Dan Walsh . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/setenforce.80100644 0000000 0000000 00000002132 13756670063 016270 0ustar000000000 0000000 .TH "setenforce" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" setenforce \- изменить режим, в котором выполняется SELinux . .SH "ОБЗОР" .B setenforce .RB [ Enforcing | Permissive | 1 | 0 ] . .SH "ОПИСАНИЕ" Используйте .B Enforcing или .B 1 для установки SELinux в принудительный режим. .br Используйте .B Permissive или .B 0 для установки SELinux в разрешительный режим. Если SELinux отключён и требуется его включить (или если SELinux включён и требуется его отключить), обратитесь к странице руководства .BR selinux (8). . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR getenforce (8), .BR selinuxenabled (8) . .SH АВТОРЫ Dan Walsh, . Перевод на русский язык выполнила Герасименко Олеся . libselinux/man/ru/man8/togglesebool.80100644 0000000 0000000 00000002147 13756670063 016626 0ustar000000000 0000000 .TH "togglesebool" "8" "26 октября 2004" "sgrubb@redhat.com" "Документация по командной строке SELinux" .SH "ИМЯ" togglesebool \- переключить текущее значение логического переключателя SELinux . .SH "ОБЗОР" .B togglesebool .I boolean... . .SH "ОПИСАНИЕ" .B togglesebool переключает текущее значение списка логических переключателей. Если текущее значение 1, то оно будет заменено на 0, и наоборот. Меняются только "находящиеся в памяти" значения; параметры загрузки остаются без изменений. . .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux (8), .BR booleans (8), .BR getsebool (8), .BR setsebool (8) . .SH АВТОРЫ Эта страница руководства была написана Steve Grubb . Перевод на русский язык выполнила Герасименко Олеся . libselinux/src/0040755 0000000 0000000 00000000000 13756670063 012572 5ustar000000000 0000000 libselinux/src/.gitignore0100644 0000000 0000000 00000000125 13756670063 014555 0ustar000000000 0000000 selinux.py selinuxswig_wrap.c selinuxswig_python_exception.i selinuxswig_ruby_wrap.c libselinux/src/Makefile0100644 0000000 0000000 00000020400 13756670063 014223 0ustar000000000 0000000 # Support building the Python bindings multiple times, against various Python # runtimes (e.g. Python 2 vs Python 3) by optionally prefixing the build # targets with "PYPREFIX": PYTHON ?= python3 PYPREFIX ?= $(shell $(PYTHON) -c 'import sys;print("python-%d.%d" % sys.version_info[:2])') RUBY ?= ruby RUBYPREFIX ?= $(notdir $(RUBY)) PKG_CONFIG ?= pkg-config # Installation directories. PREFIX ?= /usr LIBDIR ?= $(PREFIX)/lib SHLIBDIR ?= /lib INCLUDEDIR ?= $(PREFIX)/include PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX)) PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX)) PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))") PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])') RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]') RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]') RUBYINSTALL ?= $(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]') VERSION = $(shell cat ../VERSION) LIBVERSION = 1 OS ?= $(shell uname) ifeq ($(shell $(CC) -v 2>&1 | grep "clang"),) COMPILER ?= gcc else COMPILER ?= clang endif LIBA=libselinux.a TARGET=libselinux.so LIBPC=libselinux.pc SWIGIF= selinuxswig_python.i selinuxswig_python_exception.i SWIGRUBYIF= selinuxswig_ruby.i SWIGCOUT= selinuxswig_wrap.c SWIGPYOUT= selinux.py SWIGRUBYCOUT= selinuxswig_ruby_wrap.c SWIGLOBJ:= $(patsubst %.c,$(PYPREFIX)%.lo,$(SWIGCOUT)) SWIGRUBYLOBJ:= $(patsubst %.c,%.lo,$(SWIGRUBYCOUT)) SWIGSO=$(PYPREFIX)_selinux.so SWIGFILES=$(SWIGSO) $(SWIGPYOUT) SWIGRUBYSO=$(RUBYPREFIX)_selinux.so LIBSO=$(TARGET).$(LIBVERSION) AUDIT2WHYLOBJ=$(PYPREFIX)audit2why.lo AUDIT2WHYSO=$(PYPREFIX)audit2why.so # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there # is no need to define a value for LDLIBS_LIBSEPOLA ifeq ($(LIBSEPOLA),) LDLIBS_LIBSEPOLA := -l:libsepol.a endif GENERATED=$(SWIGCOUT) $(SWIGRUBYCOUT) selinuxswig_python_exception.i SRCS= $(filter-out $(GENERATED) audit2why.c, $(sort $(wildcard *.c))) MAX_STACK_SIZE=32768 ifeq ($(COMPILER), gcc) EXTRA_CFLAGS = -fipa-pure-const -Wlogical-op -Wpacked-bitfield-compat -Wsync-nand \ -Wcoverage-mismatch -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \ -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \ -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \ -Wstrict-overflow=5 else EXTRA_CFLAGS = -Wunused-command-line-argument endif OBJS= $(patsubst %.c,%.o,$(SRCS)) LOBJS= $(patsubst %.c,%.lo,$(SRCS)) CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ -Wunused -Wunknown-pragmas -Wstrict-aliasing -Wshadow -Wpointer-arith \ -Wbad-function-cast -Wcast-align -Wwrite-strings -Waggregate-return \ -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ -Wmissing-declarations -Wmissing-noreturn -Wmissing-format-attribute \ -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wvolatile-register-var \ -Wdisabled-optimization -Wbuiltin-macro-redefined \ -Wattributes -Wmultichar \ -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wendif-labels -Wextra \ -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \ -Woverflow -Wpointer-to-int-cast -Wpragmas \ -Wno-missing-field-initializers -Wno-sign-compare \ -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) \ -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \ -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \ -Werror -Wno-aggregate-return -Wno-redundant-decls \ $(EXTRA_CFLAGS) LD_SONAME_FLAGS=-soname,$(LIBSO),-z,defs,-z,relro ifeq ($(OS), Darwin) override CFLAGS += -I/opt/local/include override LDFLAGS += -L/opt/local/lib -undefined dynamic_lookup LD_SONAME_FLAGS=-install_name,$(LIBSO) endif PCRE_LDLIBS ?= -lpcre # override with -lfts when building on Musl libc to use fts-standalone FTS_LDLIBS ?= override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations RANLIB ?= ranlib ARCH := $(patsubst i%86,i386,$(shell uname -m)) ifneq (,$(filter i386,$(ARCH))) TLSFLAGS += -mno-tls-direct-seg-refs endif ifeq ($(ANDROID_HOST),y) DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \ -DBUILD_HOST SRCS= callbacks.c freecon.c label.c label_file.c \ label_backends_android.c regex.c label_support.c \ matchpathcon.c setrans_client.c sha1.c booleans.c else DISABLE_FLAGS+= -DNO_ANDROID_BACKEND SRCS:= $(filter-out label_backends_android.c, $(SRCS)) endif SWIG = swig -Wall -python -o $(SWIGCOUT) -outdir ./ $(DISABLE_FLAGS) SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ $(DISABLE_FLAGS) all: $(LIBA) $(LIBSO) $(LIBPC) pywrap: all $(SWIGFILES) $(AUDIT2WHYSO) rubywrap: all $(SWIGRUBYSO) $(SWIGLOBJ): $(SWIGCOUT) $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(PYINC) -fPIC -DSHARED -c -o $@ $< $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< $(SWIGSO): $(SWIGLOBJ) $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $< -lselinux $(PYLIBS) $(SWIGRUBYSO): $(SWIGRUBYLOBJ) $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $^ -lselinux $(RUBYLIBS) $(LIBA): $(OBJS) $(AR) rcs $@ $^ $(RANLIB) $@ $(LIBSO): $(LOBJS) $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ $(PCRE_LDLIBS) $(FTS_LDLIBS) -ldl -Wl,$(LD_SONAME_FLAGS) ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBDIR):; s:@includedir@:$(INCLUDEDIR):; s:@PCRE_MODULE@:$(PCRE_MODULE):' < $< > $@ selinuxswig_python_exception.i: ../include/selinux/selinux.h bash -e exception.sh > $@ || (rm -f $@ ; false) $(AUDIT2WHYLOBJ): audit2why.c $(CC) $(filter-out -Werror, $(CFLAGS)) $(PYINC) -fPIC -DSHARED -c -o $@ $< $(AUDIT2WHYSO): $(AUDIT2WHYLOBJ) $(LIBSEPOLA) $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $^ -lselinux $(LDLIBS_LIBSEPOLA) $(PYLIBS) -Wl,-soname,audit2why.so,--version-script=audit2why.map,-z,defs %.o: %.c policy.h $(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< %.lo: %.c policy.h $(CC) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< $(SWIGCOUT): $(SWIGIF) $(SWIG) $< $(SWIGPYOUT): $(SWIGCOUT) $(SWIGRUBYCOUT): $(SWIGRUBYIF) $(SWIGRUBY) $< swigify: $(SWIGIF) $(SWIG) $< install: all test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR) install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR) test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR) install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR) test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET) install-pywrap: pywrap test -d $(DESTDIR)$(PYTHONLIBDIR)/selinux || install -m 755 -d $(DESTDIR)$(PYTHONLIBDIR)/selinux install -m 755 $(SWIGSO) $(DESTDIR)$(PYTHONLIBDIR)/_selinux$(PYCEXT) install -m 755 $(AUDIT2WHYSO) $(DESTDIR)$(PYTHONLIBDIR)/selinux/audit2why$(PYCEXT) install -m 644 $(SWIGPYOUT) $(DESTDIR)$(PYTHONLIBDIR)/selinux/__init__.py install-rubywrap: rubywrap test -d $(DESTDIR)$(RUBYINSTALL) || install -m 755 -d $(DESTDIR)$(RUBYINSTALL) install -m 755 $(SWIGRUBYSO) $(DESTDIR)$(RUBYINSTALL)/selinux.so relabel: /sbin/restorecon $(DESTDIR)$(SHLIBDIR)/$(LIBSO) clean-pywrap: -rm -f $(SWIGLOBJ) $(SWIGSO) $(AUDIT2WHYLOBJ) $(AUDIT2WHYSO) clean-rubywrap: -rm -f $(SWIGRUBYLOBJ) $(SWIGRUBYSO) clean: clean-pywrap clean-rubywrap -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) *.o *.lo *~ distclean: clean rm -f $(GENERATED) $(SWIGFILES) indent: ../../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch])) .PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean libselinux/src/android/0040755 0000000 0000000 00000000000 13756670063 014212 5ustar000000000 0000000 libselinux/src/android/android.c0100644 0000000 0000000 00000014656 13756670063 016007 0ustar000000000 0000000 #include "android_common.h" // For 'system', 'product' (optional), 'vendor' (mandatory) and/or 'odm' (optional). #define MAX_FILE_CONTEXT_SIZE 4 #ifdef __ANDROID_VNDK__ #ifndef LOG_EVENT_STRING #define LOG_EVENT_STRING(...) #endif // LOG_EVENT_STRING #endif // __ANDROID_VNDK__ static const struct selinux_opt seopts_service_plat[] = { { SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" }, { SELABEL_OPT_PATH, "/plat_service_contexts" } }; static const struct selinux_opt seopts_service_product[] = { { SELABEL_OPT_PATH, "/product/etc/selinux/product_service_contexts" }, { SELABEL_OPT_PATH, "/product_service_contexts" } }; static const struct selinux_opt seopts_service_vendor[] = { { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_service_contexts" }, { SELABEL_OPT_PATH, "/vendor_service_contexts" }, // TODO: remove nonplat* when no need to retain backward compatibility. { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_service_contexts" }, { SELABEL_OPT_PATH, "/nonplat_service_contexts" } }; static const struct selinux_opt seopts_hwservice_plat[] = { { SELABEL_OPT_PATH, "/system/etc/selinux/plat_hwservice_contexts" }, { SELABEL_OPT_PATH, "/plat_hwservice_contexts" } }; static const struct selinux_opt seopts_hwservice_product[] = { { SELABEL_OPT_PATH, "/product/etc/selinux/product_hwservice_contexts" }, { SELABEL_OPT_PATH, "/product_hwservice_contexts" } }; static const struct selinux_opt seopts_hwservice_vendor[] = { { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_hwservice_contexts" }, { SELABEL_OPT_PATH, "/vendor_hwservice_contexts" }, // TODO: remove nonplat* when no need to retain backward compatibility. { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_hwservice_contexts" }, { SELABEL_OPT_PATH, "/nonplat_hwservice_contexts" } }; static const struct selinux_opt seopts_hwservice_odm[] = { { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_hwservice_contexts" }, { SELABEL_OPT_PATH, "/odm_hwservice_contexts" } }; static const struct selinux_opt seopts_vndservice = { SELABEL_OPT_PATH, "/vendor/etc/selinux/vndservice_contexts" }; static const struct selinux_opt seopts_vndservice_rootfs = { SELABEL_OPT_PATH, "/vndservice_contexts" }; struct selabel_handle* selinux_android_service_open_context_handle(const struct selinux_opt* seopts_service, unsigned nopts) { struct selabel_handle* sehandle; sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE, seopts_service, nopts); if (!sehandle) { selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n", __FUNCTION__, strerror(errno)); return NULL; } selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from:\n"); for (unsigned i = 0; i < nopts; i++) { selinux_log(SELINUX_INFO, " %s\n", seopts_service[i].value); } return sehandle; } struct selabel_handle* selinux_android_service_context_handle(void) { struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE]; int size = 0; unsigned int i; for (i = 0; i < ARRAY_SIZE(seopts_service_plat); i++) { if (access(seopts_service_plat[i].value, R_OK) != -1) { seopts_service[size++] = seopts_service_plat[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_service_product); i++) { if (access(seopts_service_product[i].value, R_OK) != -1) { seopts_service[size++] = seopts_service_product[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_service_vendor); i++) { if (access(seopts_service_vendor[i].value, R_OK) != -1) { seopts_service[size++] = seopts_service_vendor[i]; break; } } return selinux_android_service_open_context_handle(seopts_service, size); } struct selabel_handle* selinux_android_hw_service_context_handle(void) { struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE]; int size = 0; unsigned int i; for (i = 0; i < ARRAY_SIZE(seopts_hwservice_plat); i++) { if (access(seopts_hwservice_plat[i].value, R_OK) != -1) { seopts_service[size++] = seopts_hwservice_plat[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_hwservice_product); i++) { if (access(seopts_hwservice_product[i].value, R_OK) != -1) { seopts_service[size++] = seopts_hwservice_product[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_hwservice_vendor); i++) { if (access(seopts_hwservice_vendor[i].value, R_OK) != -1) { seopts_service[size++] = seopts_hwservice_vendor[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_hwservice_odm); i++) { if (access(seopts_hwservice_odm[i].value, R_OK) != -1) { seopts_service[size++] = seopts_hwservice_odm[i]; break; } } return selinux_android_service_open_context_handle(seopts_service, size); } struct selabel_handle* selinux_android_vendor_service_context_handle(void) { const struct selinux_opt* seopts_service; if (access(seopts_vndservice.value, R_OK) != -1) { seopts_service = &seopts_vndservice; } else { seopts_service = &seopts_vndservice_rootfs; } return selinux_android_service_open_context_handle(seopts_service, 1); } int selinux_log_callback(int type, const char *fmt, ...) { va_list ap; int priority; char *strp; switch(type) { case SELINUX_WARNING: priority = ANDROID_LOG_WARN; break; case SELINUX_INFO: priority = ANDROID_LOG_INFO; break; default: priority = ANDROID_LOG_ERROR; break; } va_start(ap, fmt); if (vasprintf(&strp, fmt, ap) != -1) { LOG_PRI(priority, "SELinux", "%s", strp); LOG_EVENT_STRING(AUDITD_LOG_TAG, strp); free(strp); } va_end(ap); return 0; } int selinux_vendor_log_callback(int type, const char *fmt, ...) { va_list ap; int priority; char *strp; switch(type) { case SELINUX_WARNING: priority = ANDROID_LOG_WARN; break; case SELINUX_INFO: priority = ANDROID_LOG_INFO; break; default: priority = ANDROID_LOG_ERROR; break; } va_start(ap, fmt); if (vasprintf(&strp, fmt, ap) != -1) { LOG_PRI(priority, "SELinux", "%s", strp); free(strp); } va_end(ap); return 0; } libselinux/src/android/android_common.h0100644 0000000 0000000 00000001746 13756670063 017360 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __ANDROID_VNDK__ #include #endif #include #include "policy.h" #include "callbacks.h" #include "selinux_internal.h" #include "label_internal.h" #include #include #include #include #include #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define FC_DIGEST_SIZE SHA_DIGEST_LENGTH libselinux/src/android/android_host.c0100644 0000000 0000000 00000000270 13756670063 017027 0ustar000000000 0000000 #include // HACK: placeholder for a library the python bindings expect. // Delete after b/33170640 is fixed. const char *selinux_openssh_contexts_path(void) { abort(); } libselinux/src/android/android_platform.c0100644 0000000 0000000 00000150673 13756670063 017713 0ustar000000000 0000000 #include "android_common.h" #include // For 'system', 'product' (optional), 'vendor' (mandatory) and/or 'odm' (optional). #define MAX_FILE_CONTEXT_SIZE 4 static const char *const sepolicy_file = "/sepolicy"; static const struct selinux_opt seopts_file_plat[] = { { SELABEL_OPT_PATH, "/system/etc/selinux/plat_file_contexts" }, { SELABEL_OPT_PATH, "/plat_file_contexts" } }; static const struct selinux_opt seopts_file_product[] = { { SELABEL_OPT_PATH, "/product/etc/selinux/product_file_contexts" }, { SELABEL_OPT_PATH, "/product_file_contexts" } }; static const struct selinux_opt seopts_file_vendor[] = { { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_file_contexts" }, { SELABEL_OPT_PATH, "/vendor_file_contexts" }, // TODO: remove nonplat* when no need to retain backward compatibility. { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_file_contexts" }, { SELABEL_OPT_PATH, "/nonplat_file_contexts" } }; static const struct selinux_opt seopts_file_odm[] = { { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_file_contexts" }, { SELABEL_OPT_PATH, "/odm_file_contexts" } }; static const struct selinux_opt seopts_prop_plat[] = { { SELABEL_OPT_PATH, "/system/etc/selinux/plat_property_contexts" }, { SELABEL_OPT_PATH, "/plat_property_contexts" } }; static const struct selinux_opt seopts_prop_product[] = { { SELABEL_OPT_PATH, "/product/etc/selinux/product_property_contexts" }, { SELABEL_OPT_PATH, "/product_property_contexts" } }; static const struct selinux_opt seopts_prop_vendor[] = { { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_property_contexts" }, { SELABEL_OPT_PATH, "/vendor_property_contexts" }, // TODO: remove nonplat* when no need to retain backward compatibility. { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_property_contexts" }, { SELABEL_OPT_PATH, "/nonplat_property_contexts" } }; static const struct selinux_opt seopts_prop_odm[] = { { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_property_contexts" }, { SELABEL_OPT_PATH, "/odm_property_contexts" } }; /* * XXX Where should this configuration file be located? * Needs to be accessible by zygote and installd when * setting credentials for app processes and setting permissions * on app data directories. */ static char const * const seapp_contexts_plat[] = { "/system/etc/selinux/plat_seapp_contexts", "/plat_seapp_contexts" }; static char const * const seapp_contexts_product[] = { "/product/etc/selinux/product_seapp_contexts", "/product_seapp_contexts" }; static char const * const seapp_contexts_vendor[] = { "/vendor/etc/selinux/vendor_seapp_contexts", "/vendor_seapp_contexts", // TODO: remove nonplat* when no need to retain backward compatibility. "/vendor/etc/selinux/nonplat_seapp_contexts", "/nonplat_seapp_contexts" }; static char const * const seapp_contexts_odm[] = { "/odm/etc/selinux/odm_seapp_contexts", "/odm_seapp_contexts" }; uint8_t fc_digest[FC_DIGEST_SIZE]; static bool compute_file_contexts_hash(uint8_t c_digest[], const struct selinux_opt *opts, unsigned nopts) { int fd = -1; void *map = MAP_FAILED; bool ret = false; uint8_t *fc_data = NULL; size_t total_size = 0; struct stat sb; size_t i; for (i = 0; i < nopts; i++) { fd = open(opts[i].value, O_CLOEXEC | O_RDONLY); if (fd < 0) { selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n", opts[i].value, strerror(errno)); goto cleanup; } if (fstat(fd, &sb) < 0) { selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", opts[i].value, strerror(errno)); goto cleanup; } if (sb.st_size == 0) { selinux_log(SELINUX_WARNING, "SELinux: Skipping %s: empty file\n", opts[i].value); goto nextfile; } map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", opts[i].value, strerror(errno)); goto cleanup; } fc_data = realloc(fc_data, total_size + sb.st_size); if (!fc_data) { selinux_log(SELINUX_ERROR, "SELinux: Count not re-alloc for %s: %s\n", opts[i].value, strerror(errno)); goto cleanup; } memcpy(fc_data + total_size, map, sb.st_size); total_size += sb.st_size; /* reset everything for next file */ munmap(map, sb.st_size); nextfile: close(fd); map = MAP_FAILED; fd = -1; } SHA1(fc_data, total_size, c_digest); ret = true; cleanup: if (map != MAP_FAILED) munmap(map, sb.st_size); if (fd >= 0) close(fd); free(fc_data); return ret; } static struct selabel_handle* selinux_android_file_context(const struct selinux_opt *opts, unsigned nopts) { struct selabel_handle *sehandle; struct selinux_opt fc_opts[nopts + 1]; memcpy(fc_opts, opts, nopts*sizeof(struct selinux_opt)); fc_opts[nopts].type = SELABEL_OPT_BASEONLY; fc_opts[nopts].value = (char *)1; sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, ARRAY_SIZE(fc_opts)); if (!sehandle) { selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n", __FUNCTION__, strerror(errno)); return NULL; } if (!compute_file_contexts_hash(fc_digest, opts, nopts)) { selabel_close(sehandle); return NULL; } selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts\n"); return sehandle; } struct selabel_handle* selinux_android_file_context_handle(void) { struct selinux_opt seopts_file[MAX_FILE_CONTEXT_SIZE]; int size = 0; unsigned int i; for (i = 0; i < ARRAY_SIZE(seopts_file_plat); i++) { if (access(seopts_file_plat[i].value, R_OK) != -1) { seopts_file[size++] = seopts_file_plat[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_file_product); i++) { if (access(seopts_file_product[i].value, R_OK) != -1) { seopts_file[size++] = seopts_file_product[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_file_vendor); i++) { if (access(seopts_file_vendor[i].value, R_OK) != -1) { seopts_file[size++] = seopts_file_vendor[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_file_odm); i++) { if (access(seopts_file_odm[i].value, R_OK) != -1) { seopts_file[size++] = seopts_file_odm[i]; break; } } return selinux_android_file_context(seopts_file, size); } struct selabel_handle* selinux_android_prop_context_handle(void) { struct selabel_handle* sehandle; struct selinux_opt seopts_prop[MAX_FILE_CONTEXT_SIZE]; int size = 0; unsigned int i; for (i = 0; i < ARRAY_SIZE(seopts_prop_plat); i++) { if (access(seopts_prop_plat[i].value, R_OK) != -1) { seopts_prop[size++] = seopts_prop_plat[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_prop_product); i++) { if (access(seopts_prop_product[i].value, R_OK) != -1) { seopts_prop[size++] = seopts_prop_product[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_prop_vendor); i++) { if (access(seopts_prop_vendor[i].value, R_OK) != -1) { seopts_prop[size++] = seopts_prop_vendor[i]; break; } } for (i = 0; i < ARRAY_SIZE(seopts_prop_odm); i++) { if (access(seopts_prop_odm[i].value, R_OK) != -1) { seopts_prop[size++] = seopts_prop_odm[i]; break; } } sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, seopts_prop, size); if (!sehandle) { selinux_log(SELINUX_ERROR, "%s: Error getting property context handle (%s)\n", __FUNCTION__, strerror(errno)); return NULL; } selinux_log(SELINUX_INFO, "SELinux: Loaded property_contexts from %s & %s.\n", seopts_prop[0].value, seopts_prop[1].value); return sehandle; } enum levelFrom { LEVELFROM_NONE, LEVELFROM_APP, LEVELFROM_USER, LEVELFROM_ALL }; #if DEBUG static char const * const levelFromName[] = { "none", "app", "user", "all" }; #endif struct prefix_str { size_t len; char *str; char is_prefix; }; static void free_prefix_str(struct prefix_str *p) { if (!p) return; free(p->str); } struct seapp_context { /* input selectors */ bool isSystemServer; bool isEphemeralAppSet; bool isEphemeralApp; bool isV2AppSet; bool isV2App; bool isOwnerSet; bool isOwner; struct prefix_str user; char *seinfo; struct prefix_str name; struct prefix_str path; bool isPrivAppSet; bool isPrivApp; int32_t minTargetSdkVersion; bool fromRunAs; /* outputs */ char *domain; char *type; char *level; enum levelFrom levelFrom; }; static void free_seapp_context(struct seapp_context *s) { if (!s) return; free_prefix_str(&s->user); free(s->seinfo); free_prefix_str(&s->name); free_prefix_str(&s->path); free(s->domain); free(s->type); free(s->level); } static bool seapp_contexts_dup = false; static int seapp_context_cmp(const void *A, const void *B) { const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A; const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B; const struct seapp_context *s1 = *sp1, *s2 = *sp2; bool dup; /* Give precedence to isSystemServer=true. */ if (s1->isSystemServer != s2->isSystemServer) return (s1->isSystemServer ? -1 : 1); /* Give precedence to a specified isEphemeral= over an * unspecified isEphemeral=. */ if (s1->isEphemeralAppSet != s2->isEphemeralAppSet) return (s1->isEphemeralAppSet ? -1 : 1); /* Give precedence to a specified isV2= over an * unspecified isV2=. */ if (s1->isV2AppSet != s2->isV2AppSet) return (s1->isV2AppSet ? -1 : 1); /* Give precedence to a specified isOwner= over an unspecified isOwner=. */ if (s1->isOwnerSet != s2->isOwnerSet) return (s1->isOwnerSet ? -1 : 1); /* Give precedence to a specified user= over an unspecified user=. */ if (s1->user.str && !s2->user.str) return -1; if (!s1->user.str && s2->user.str) return 1; if (s1->user.str) { /* Give precedence to a fixed user= string over a prefix. */ if (s1->user.is_prefix != s2->user.is_prefix) return (s2->user.is_prefix ? -1 : 1); /* Give precedence to a longer prefix over a shorter prefix. */ if (s1->user.is_prefix && s1->user.len != s2->user.len) return (s1->user.len > s2->user.len) ? -1 : 1; } /* Give precedence to a specified seinfo= over an unspecified seinfo=. */ if (s1->seinfo && !s2->seinfo) return -1; if (!s1->seinfo && s2->seinfo) return 1; /* Give precedence to a specified name= over an unspecified name=. */ if (s1->name.str && !s2->name.str) return -1; if (!s1->name.str && s2->name.str) return 1; if (s1->name.str) { /* Give precedence to a fixed name= string over a prefix. */ if (s1->name.is_prefix != s2->name.is_prefix) return (s2->name.is_prefix ? -1 : 1); /* Give precedence to a longer prefix over a shorter prefix. */ if (s1->name.is_prefix && s1->name.len != s2->name.len) return (s1->name.len > s2->name.len) ? -1 : 1; } /* Give precedence to a specified path= over an unspecified path=. */ if (s1->path.str && !s2->path.str) return -1; if (!s1->path.str && s2->path.str) return 1; if (s1->path.str) { /* Give precedence to a fixed path= string over a prefix. */ if (s1->path.is_prefix != s2->path.is_prefix) return (s2->path.is_prefix ? -1 : 1); /* Give precedence to a longer prefix over a shorter prefix. */ if (s1->path.is_prefix && s1->path.len != s2->path.len) return (s1->path.len > s2->path.len) ? -1 : 1; } /* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */ if (s1->isPrivAppSet != s2->isPrivAppSet) return (s1->isPrivAppSet ? -1 : 1); /* Give precedence to a higher minTargetSdkVersion= over a lower minTargetSdkVersion=. * If unspecified, minTargetSdkVersion has a default value of 0. */ if (s1->minTargetSdkVersion > s2->minTargetSdkVersion) return -1; else if (s1->minTargetSdkVersion < s2->minTargetSdkVersion) return 1; /* Give precedence to fromRunAs=true. */ if (s1->fromRunAs != s2->fromRunAs) return (s1->fromRunAs ? -1 : 1); /* * Check for a duplicated entry on the input selectors. * We already compared isSystemServer, isOwnerSet, and isOwner above. * We also have already checked that both entries specify the same * string fields, so if s1 has a non-NULL string, then so does s2. */ dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) && (!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) && (!s1->name.str || !strcmp(s1->name.str, s2->name.str)) && (!s1->path.str || !strcmp(s1->path.str, s2->path.str)) && (s1->isPrivAppSet && s1->isPrivApp == s2->isPrivApp) && (s1->isOwnerSet && s1->isOwner == s2->isOwner) && (s1->isSystemServer && s1->isSystemServer == s2->isSystemServer) && (s1->isV2AppSet && s1->isV2App == s2->isV2App) && (s1->isEphemeralAppSet && s1->isEphemeralApp == s2->isEphemeralApp); if (dup) { seapp_contexts_dup = true; selinux_log(SELINUX_ERROR, "seapp_contexts: Duplicated entry\n"); if (s1->user.str) selinux_log(SELINUX_ERROR, " user=%s\n", s1->user.str); if (s1->seinfo) selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo); if (s1->name.str) selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str); if (s1->path.str) selinux_log(SELINUX_ERROR, " path=%s\n", s1->path.str); } /* Anything else has equal precedence. */ return 0; } static struct seapp_context **seapp_contexts = NULL; static int nspec = 0; static void free_seapp_contexts(void) { int n; if (!seapp_contexts) return; for (n = 0; n < nspec; n++) free_seapp_context(seapp_contexts[n]); free(seapp_contexts); seapp_contexts = NULL; nspec = 0; } static int32_t get_minTargetSdkVersion(const char *value) { char *endptr; long minTargetSdkVersion; minTargetSdkVersion = strtol(value, &endptr, 10); if (('\0' != *endptr) || (minTargetSdkVersion < 0) || (minTargetSdkVersion > INT32_MAX)) { return -1; /* error parsing minTargetSdkVersion */ } else { return (int32_t) minTargetSdkVersion; } } int selinux_android_seapp_context_reload(void) { FILE *fp = NULL; char line_buf[BUFSIZ]; char *token; unsigned lineno; struct seapp_context *cur; char *p, *name = NULL, *value = NULL, *saveptr; size_t i, len, files_len = 0; int ret; const char* seapp_contexts_files[MAX_FILE_CONTEXT_SIZE]; for (i = 0; i < ARRAY_SIZE(seapp_contexts_plat); i++) { if (access(seapp_contexts_plat[i], R_OK) != -1) { seapp_contexts_files[files_len++] = seapp_contexts_plat[i]; break; } } for (i = 0; i < ARRAY_SIZE(seapp_contexts_product); i++) { if (access(seapp_contexts_product[i], R_OK) != -1) { seapp_contexts_files[files_len++] = seapp_contexts_product[i]; break; } } for (i = 0; i < ARRAY_SIZE(seapp_contexts_vendor); i++) { if (access(seapp_contexts_vendor[i], R_OK) != -1) { seapp_contexts_files[files_len++] = seapp_contexts_vendor[i]; break; } } for (i = 0; i < ARRAY_SIZE(seapp_contexts_odm); i++) { if (access(seapp_contexts_odm[i], R_OK) != -1) { seapp_contexts_files[files_len++] = seapp_contexts_odm[i]; break; } } free_seapp_contexts(); nspec = 0; for (i = 0; i < files_len; i++) { fp = fopen(seapp_contexts_files[i], "re"); if (!fp) { selinux_log(SELINUX_ERROR, "%s: could not open seapp_contexts file: %s", __FUNCTION__, seapp_contexts_files[i]); return -1; } while (fgets(line_buf, sizeof line_buf - 1, fp)) { p = line_buf; while (isspace(*p)) p++; if (*p == '#' || *p == 0) continue; nspec++; } fclose(fp); } seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *)); if (!seapp_contexts) goto oom; nspec = 0; for (i = 0; i < files_len; i++) { lineno = 1; fp = fopen(seapp_contexts_files[i], "re"); if (!fp) { selinux_log(SELINUX_ERROR, "%s: could not open seapp_contexts file: %s", __FUNCTION__, seapp_contexts_files[i]); free_seapp_contexts(); return -1; } while (fgets(line_buf, sizeof line_buf - 1, fp)) { len = strlen(line_buf); if (len == 0) { // line contains a NUL byte as its first entry goto err; } if (line_buf[len - 1] == '\n') line_buf[len - 1] = 0; p = line_buf; while (isspace(*p)) p++; if (*p == '#' || *p == 0) continue; cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context)); if (!cur) goto oom; token = strtok_r(p, " \t", &saveptr); if (!token) { free_seapp_context(cur); goto err; } while (1) { name = token; value = strchr(name, '='); if (!value) { free_seapp_context(cur); goto err; } *value++ = 0; if (!strcasecmp(name, "isSystemServer")) { if (!strcasecmp(value, "true")) cur->isSystemServer = true; else if (!strcasecmp(value, "false")) cur->isSystemServer = false; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "isEphemeralApp")) { cur->isEphemeralAppSet = true; if (!strcasecmp(value, "true")) cur->isEphemeralApp = true; else if (!strcasecmp(value, "false")) cur->isEphemeralApp = false; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "isV2App")) { cur->isV2AppSet = true; if (!strcasecmp(value, "true")) cur->isV2App = true; else if (!strcasecmp(value, "false")) cur->isV2App = false; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "isOwner")) { cur->isOwnerSet = true; if (!strcasecmp(value, "true")) cur->isOwner = true; else if (!strcasecmp(value, "false")) cur->isOwner = false; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "user")) { if (cur->user.str) { free_seapp_context(cur); goto err; } cur->user.str = strdup(value); if (!cur->user.str) { free_seapp_context(cur); goto oom; } cur->user.len = strlen(cur->user.str); if (cur->user.str[cur->user.len-1] == '*') cur->user.is_prefix = 1; } else if (!strcasecmp(name, "seinfo")) { if (cur->seinfo) { free_seapp_context(cur); goto err; } cur->seinfo = strdup(value); if (!cur->seinfo) { free_seapp_context(cur); goto oom; } if (strstr(value, ":")) { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "name")) { if (cur->name.str) { free_seapp_context(cur); goto err; } cur->name.str = strdup(value); if (!cur->name.str) { free_seapp_context(cur); goto oom; } cur->name.len = strlen(cur->name.str); if (cur->name.str[cur->name.len-1] == '*') cur->name.is_prefix = 1; } else if (!strcasecmp(name, "domain")) { if (cur->domain) { free_seapp_context(cur); goto err; } cur->domain = strdup(value); if (!cur->domain) { free_seapp_context(cur); goto oom; } } else if (!strcasecmp(name, "type")) { if (cur->type) { free_seapp_context(cur); goto err; } cur->type = strdup(value); if (!cur->type) { free_seapp_context(cur); goto oom; } } else if (!strcasecmp(name, "levelFromUid")) { if (cur->levelFrom) { free_seapp_context(cur); goto err; } if (!strcasecmp(value, "true")) cur->levelFrom = LEVELFROM_APP; else if (!strcasecmp(value, "false")) cur->levelFrom = LEVELFROM_NONE; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "levelFrom")) { if (cur->levelFrom) { free_seapp_context(cur); goto err; } if (!strcasecmp(value, "none")) cur->levelFrom = LEVELFROM_NONE; else if (!strcasecmp(value, "app")) cur->levelFrom = LEVELFROM_APP; else if (!strcasecmp(value, "user")) cur->levelFrom = LEVELFROM_USER; else if (!strcasecmp(value, "all")) cur->levelFrom = LEVELFROM_ALL; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "level")) { if (cur->level) { free_seapp_context(cur); goto err; } cur->level = strdup(value); if (!cur->level) { free_seapp_context(cur); goto oom; } } else if (!strcasecmp(name, "path")) { if (cur->path.str) { free_seapp_context(cur); goto err; } cur->path.str = strdup(value); if (!cur->path.str) { free_seapp_context(cur); goto oom; } cur->path.len = strlen(cur->path.str); if (cur->path.str[cur->path.len-1] == '*') cur->path.is_prefix = 1; } else if (!strcasecmp(name, "isPrivApp")) { cur->isPrivAppSet = true; if (!strcasecmp(value, "true")) cur->isPrivApp = true; else if (!strcasecmp(value, "false")) cur->isPrivApp = false; else { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "minTargetSdkVersion")) { cur->minTargetSdkVersion = get_minTargetSdkVersion(value); if (cur->minTargetSdkVersion < 0) { free_seapp_context(cur); goto err; } } else if (!strcasecmp(name, "fromRunAs")) { if (!strcasecmp(value, "true")) cur->fromRunAs = true; else if (!strcasecmp(value, "false")) cur->fromRunAs = false; else { free_seapp_context(cur); goto err; } } else { free_seapp_context(cur); goto err; } token = strtok_r(NULL, " \t", &saveptr); if (!token) break; } if (cur->name.str && (!cur->seinfo || !strcmp(cur->seinfo, "default"))) { selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n", seapp_contexts_files[i], cur->name.str, lineno); free_seapp_context(cur); goto err; } seapp_contexts[nspec] = cur; nspec++; lineno++; } fclose(fp); fp = NULL; } qsort(seapp_contexts, nspec, sizeof(struct seapp_context *), seapp_context_cmp); if (seapp_contexts_dup) goto err_no_log; #if DEBUG { int i; for (i = 0; i < nspec; i++) { cur = seapp_contexts[i]; selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isEphemeralApp=%s isV2App=%s isOwner=%s user=%s seinfo=%s " "name=%s path=%s isPrivApp=%s minTargetSdkVersion=%d fromRunAs=%s -> domain=%s type=%s level=%s levelFrom=%s", __FUNCTION__, cur->isSystemServer ? "true" : "false", cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null", cur->isV2AppSet ? (cur->isV2App ? "true" : "false") : "null", cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null", cur->user.str, cur->seinfo, cur->name.str, cur->path.str, cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null", cur->minTargetSdkVersion, cur->fromRunAs ? "true" : "false", cur->domain, cur->type, cur->level, levelFromName[cur->levelFrom]); } } #endif ret = 0; out: if (fp) { fclose(fp); } return ret; err: selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n", seapp_contexts_files[i], lineno); err_no_log: free_seapp_contexts(); ret = -1; goto out; oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); free_seapp_contexts(); ret = -1; goto out; } static void seapp_context_init(void) { selinux_android_seapp_context_reload(); } static pthread_once_t once = PTHREAD_ONCE_INIT; void selinux_android_seapp_context_init(void) { __selinux_once(once, seapp_context_init); } /* * Max id that can be mapped to category set uniquely * using the current scheme. */ #define CAT_MAPPING_MAX_ID (0x1<<16) enum seapp_kind { SEAPP_TYPE, SEAPP_DOMAIN }; #define PRIVILEGED_APP_STR ":privapp" #define EPHEMERAL_APP_STR ":ephemeralapp" #define V2_APP_STR ":v2" #define TARGETSDKVERSION_STR ":targetSdkVersion=" #define FROM_RUNAS_STR ":fromRunAs" static int32_t get_app_targetSdkVersion(const char *seinfo) { char *substr = strstr(seinfo, TARGETSDKVERSION_STR); long targetSdkVersion; char *endptr; if (substr != NULL) { substr = substr + strlen(TARGETSDKVERSION_STR); if (substr != NULL) { targetSdkVersion = strtol(substr, &endptr, 10); if (('\0' != *endptr && ':' != *endptr) || (targetSdkVersion < 0) || (targetSdkVersion > INT32_MAX)) { return -1; /* malformed targetSdkVersion value in seinfo */ } else { return (int32_t) targetSdkVersion; } } } return 0; /* default to 0 when targetSdkVersion= is not present in seinfo */ } static int seinfo_parse(char *dest, const char *src, size_t size) { size_t len; char *p; if ((p = strchr(src, ':')) != NULL) len = p - src; else len = strlen(src); if (len > size - 1) return -1; strncpy(dest, src, len); dest[len] = '\0'; return 0; } static int seapp_context_lookup(enum seapp_kind kind, uid_t uid, bool isSystemServer, const char *seinfo, const char *pkgname, const char *path, context_t ctx) { struct passwd *pwd; bool isOwner; const char *username = NULL; struct seapp_context *cur = NULL; int i; uid_t userid; uid_t appid; bool isPrivApp = false; bool isEphemeralApp = false; int32_t targetSdkVersion = 0; bool isV2App = false; bool fromRunAs = false; char parsedseinfo[BUFSIZ]; selinux_android_seapp_context_init(); if (seinfo) { if (seinfo_parse(parsedseinfo, seinfo, BUFSIZ)) goto err; isPrivApp = strstr(seinfo, PRIVILEGED_APP_STR) ? true : false; isEphemeralApp = strstr(seinfo, EPHEMERAL_APP_STR) ? true : false; isV2App = strstr(seinfo, V2_APP_STR) ? true : false; fromRunAs = strstr(seinfo, FROM_RUNAS_STR) ? true : false; targetSdkVersion = get_app_targetSdkVersion(seinfo); if (targetSdkVersion < 0) { selinux_log(SELINUX_ERROR, "%s: Invalid targetSdkVersion passed for app with uid %d, seinfo %s, name %s\n", __FUNCTION__, uid, seinfo, pkgname); goto err; } seinfo = parsedseinfo; } userid = uid / AID_USER; isOwner = (userid == 0); appid = uid % AID_USER; if (appid < AID_APP) { /* * This code is Android specific, bionic guarantees that * calls to non-reentrant getpwuid() are thread safe. */ #ifndef __BIONIC__ #warning "This code assumes that getpwuid is thread safe, only true with Bionic!" #endif pwd = getpwuid(appid); if (!pwd) goto err; username = pwd->pw_name; } else if (appid < AID_ISOLATED_START) { username = "_app"; appid -= AID_APP; } else { username = "_isolated"; appid -= AID_ISOLATED_START; } if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) goto err; for (i = 0; i < nspec; i++) { cur = seapp_contexts[i]; if (cur->isSystemServer != isSystemServer) continue; if (cur->isEphemeralAppSet && cur->isEphemeralApp != isEphemeralApp) continue; if (cur->isV2AppSet && cur->isV2App != isV2App) continue; if (cur->isOwnerSet && cur->isOwner != isOwner) continue; if (cur->user.str) { if (cur->user.is_prefix) { if (strncasecmp(username, cur->user.str, cur->user.len-1)) continue; } else { if (strcasecmp(username, cur->user.str)) continue; } } if (cur->seinfo) { if (!seinfo || strcasecmp(seinfo, cur->seinfo)) continue; } if (cur->name.str) { if(!pkgname) continue; if (cur->name.is_prefix) { if (strncasecmp(pkgname, cur->name.str, cur->name.len-1)) continue; } else { if (strcasecmp(pkgname, cur->name.str)) continue; } } if (cur->isPrivAppSet && cur->isPrivApp != isPrivApp) continue; if (cur->minTargetSdkVersion > targetSdkVersion) continue; if (cur->fromRunAs != fromRunAs) continue; if (cur->path.str) { if (!path) continue; if (cur->path.is_prefix) { if (strncmp(path, cur->path.str, cur->path.len-1)) continue; } else { if (strcmp(path, cur->path.str)) continue; } } if (kind == SEAPP_TYPE && !cur->type) continue; else if (kind == SEAPP_DOMAIN && !cur->domain) continue; if (kind == SEAPP_TYPE) { if (context_type_set(ctx, cur->type)) goto oom; } else if (kind == SEAPP_DOMAIN) { if (context_type_set(ctx, cur->domain)) goto oom; } if (cur->levelFrom != LEVELFROM_NONE) { char level[255]; switch (cur->levelFrom) { case LEVELFROM_APP: snprintf(level, sizeof level, "s0:c%u,c%u", appid & 0xff, 256 + (appid>>8 & 0xff)); break; case LEVELFROM_USER: snprintf(level, sizeof level, "s0:c%u,c%u", 512 + (userid & 0xff), 768 + (userid>>8 & 0xff)); break; case LEVELFROM_ALL: snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u", appid & 0xff, 256 + (appid>>8 & 0xff), 512 + (userid & 0xff), 768 + (userid>>8 & 0xff)); break; default: goto err; } if (context_range_set(ctx, level)) goto oom; } else if (cur->level) { if (context_range_set(ctx, cur->level)) goto oom; } break; } if (kind == SEAPP_DOMAIN && i == nspec) { /* * No match. * Fail to prevent staying in the zygote's context. */ selinux_log(SELINUX_ERROR, "%s: No match for app with uid %d, seinfo %s, name %s\n", __FUNCTION__, uid, seinfo, pkgname); if (security_getenforce() == 1) goto err; } return 0; err: return -1; oom: return -2; } int selinux_android_setfilecon(const char *pkgdir, const char *pkgname, const char *seinfo, uid_t uid) { char *orig_ctx_str = NULL; char *ctx_str = NULL; context_t ctx = NULL; int rc = -1; if (is_selinux_enabled() <= 0) return 0; rc = getfilecon(pkgdir, &ctx_str); if (rc < 0) goto err; ctx = context_new(ctx_str); orig_ctx_str = ctx_str; if (!ctx) goto oom; rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx); if (rc == -1) goto err; else if (rc == -2) goto oom; ctx_str = context_str(ctx); if (!ctx_str) goto oom; rc = security_check_context(ctx_str); if (rc < 0) goto err; if (strcmp(ctx_str, orig_ctx_str)) { rc = setfilecon(pkgdir, ctx_str); if (rc < 0) goto err; } rc = 0; out: freecon(orig_ctx_str); context_free(ctx); return rc; err: selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n", __FUNCTION__, pkgdir, uid, strerror(errno)); rc = -1; goto out; oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); rc = -1; goto out; } int selinux_android_setcon(const char *con) { int ret = setcon(con); if (ret) return ret; /* System properties must be reinitialized after setcon() otherwise the previous property files will be leaked since mmap()'ed regions are not closed as a result of setcon(). */ return __system_properties_init(); } int selinux_android_setcontext(uid_t uid, bool isSystemServer, const char *seinfo, const char *pkgname) { char *orig_ctx_str = NULL, *ctx_str; context_t ctx = NULL; int rc = -1; if (is_selinux_enabled() <= 0) return 0; rc = getcon(&ctx_str); if (rc) goto err; ctx = context_new(ctx_str); orig_ctx_str = ctx_str; if (!ctx) goto oom; rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx); if (rc == -1) goto err; else if (rc == -2) goto oom; ctx_str = context_str(ctx); if (!ctx_str) goto oom; rc = security_check_context(ctx_str); if (rc < 0) goto err; if (strcmp(ctx_str, orig_ctx_str)) { rc = selinux_android_setcon(ctx_str); if (rc < 0) goto err; } rc = 0; out: freecon(orig_ctx_str); context_free(ctx); avc_netlink_close(); return rc; err: if (isSystemServer) selinux_log(SELINUX_ERROR, "%s: Error setting context for system server: %s\n", __FUNCTION__, strerror(errno)); else selinux_log(SELINUX_ERROR, "%s: Error setting context for app with uid %d, seinfo %s: %s\n", __FUNCTION__, uid, seinfo, strerror(errno)); rc = -1; goto out; oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); rc = -1; goto out; } static struct selabel_handle *fc_sehandle = NULL; static void file_context_init(void) { if (!fc_sehandle) fc_sehandle = selinux_android_file_context_handle(); } static pthread_once_t fc_once = PTHREAD_ONCE_INIT; #define PKGTAB_SIZE 256 static struct pkg_info *pkgTab[PKGTAB_SIZE]; static unsigned int pkghash(const char *pkgname) { unsigned int h = 7; for (; *pkgname; pkgname++) { h = h * 31 + *pkgname; } return h & (PKGTAB_SIZE - 1); } static bool pkg_parse_callback(pkg_info *info, void *userdata) { (void) userdata; unsigned int hash = pkghash(info->name); if (pkgTab[hash]) info->private_data = pkgTab[hash]; pkgTab[hash] = info; return true; } static void package_info_init(void) { bool rc = packagelist_parse(pkg_parse_callback, NULL); if (!rc) { selinux_log(SELINUX_ERROR, "SELinux: Could NOT parse package list\n"); return; } #if DEBUG { unsigned int hash, buckets, entries, chainlen, longestchain; struct pkg_info *info = NULL; buckets = entries = longestchain = 0; for (hash = 0; hash < PKGTAB_SIZE; hash++) { if (pkgTab[hash]) { buckets++; chainlen = 0; for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) { chainlen++; selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n", __FUNCTION__, info->name, info->uid, info->debuggable ? "true" : "false", info->data_dir, info->seinfo); } entries += chainlen; if (longestchain < chainlen) longestchain = chainlen; } } selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain); } #endif } static pthread_once_t pkg_once = PTHREAD_ONCE_INIT; struct pkg_info *package_info_lookup(const char *name) { struct pkg_info *info; unsigned int hash; __selinux_once(pkg_once, package_info_init); hash = pkghash(name); for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) { if (!strcmp(name, info->name)) return info; } return NULL; } /* The contents of these paths are encrypted on FBE devices until user * credentials are presented (filenames inside are mangled), so we need * to delay restorecon of those until vold explicitly requests it. */ // NOTE: these paths need to be kept in sync with vold #define DATA_SYSTEM_CE_PREFIX "/data/system_ce/" #define DATA_VENDOR_CE_PREFIX "/data/vendor_ce/" #define DATA_MISC_CE_PREFIX "/data/misc_ce/" /* The path prefixes of package data directories. */ #define DATA_DATA_PATH "/data/data" #define DATA_USER_PATH "/data/user" #define DATA_USER_DE_PATH "/data/user_de" #define EXPAND_USER_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user" #define EXPAND_USER_DE_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user_de" #define DATA_DATA_PREFIX DATA_DATA_PATH "/" #define DATA_USER_PREFIX DATA_USER_PATH "/" #define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/" static int pkgdir_selabel_lookup(const char *pathname, const char *seinfo, uid_t uid, char **secontextp) { char *pkgname = NULL, *end = NULL; struct pkg_info *info = NULL; char *secontext = *secontextp; context_t ctx = NULL; int rc = 0; /* Skip directory prefix before package name. */ if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) { pathname += sizeof(DATA_DATA_PREFIX) - 1; } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) { pathname += sizeof(DATA_USER_PREFIX) - 1; while (isdigit(*pathname)) pathname++; if (*pathname == '/') pathname++; else return 0; } else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) { pathname += sizeof(DATA_USER_DE_PREFIX) - 1; while (isdigit(*pathname)) pathname++; if (*pathname == '/') pathname++; else return 0; } else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { pathname += sizeof(EXPAND_USER_PATH); while (isdigit(*pathname)) pathname++; if (*pathname == '/') pathname++; else return 0; } else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { pathname += sizeof(EXPAND_USER_DE_PATH); while (isdigit(*pathname)) pathname++; if (*pathname == '/') pathname++; else return 0; } else return 0; if (!(*pathname)) return 0; pkgname = strdup(pathname); if (!pkgname) return -1; for (end = pkgname; *end && *end != '/'; end++) ; pathname = end; if (*end) pathname++; *end = '\0'; if (!seinfo) { info = package_info_lookup(pkgname); if (!info) { selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n", pkgname, pathname); free(pkgname); return -1; } } ctx = context_new(secontext); if (!ctx) goto err; rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0, info ? info->seinfo : seinfo, info ? info->name : pkgname, pathname, ctx); if (rc < 0) goto err; secontext = context_str(ctx); if (!secontext) goto err; if (!strcmp(secontext, *secontextp)) goto out; rc = security_check_context(secontext); if (rc < 0) goto err; freecon(*secontextp); *secontextp = strdup(secontext); if (!(*secontextp)) goto err; rc = 0; out: free(pkgname); context_free(ctx); return rc; err: selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n", __FUNCTION__, pathname, pkgname, info->seinfo, info->uid, strerror(errno)); rc = -1; goto out; } #define RESTORECON_PARTIAL_MATCH_DIGEST "security.sehash" static int restorecon_sb(const char *pathname, const struct stat *sb, bool nochange, bool verbose, const char *seinfo, uid_t uid) { char *secontext = NULL; char *oldsecontext = NULL; int rc = 0; if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0) return 0; /* no match, but not an error */ if (lgetfilecon(pathname, &oldsecontext) < 0) goto err; /* * For subdirectories of /data/data or /data/user, we ignore selabel_lookup() * and use pkgdir_selabel_lookup() instead. Files within those directories * have different labeling rules, based off of /seapp_contexts, and * installd is responsible for managing these labels instead of init. */ if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) || !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0) goto err; } if (strcmp(oldsecontext, secontext) != 0) { if (verbose) selinux_log(SELINUX_INFO, "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext); if (!nochange) { if (lsetfilecon(pathname, secontext) < 0) goto err; } } rc = 0; out: freecon(oldsecontext); freecon(secontext); return rc; err: selinux_log(SELINUX_ERROR, "SELinux: Could not set context for %s: %s\n", pathname, strerror(errno)); rc = -1; goto out; } #define SYS_PATH "/sys" #define SYS_PREFIX SYS_PATH "/" struct dir_hash_node { char* path; uint8_t digest[SHA1_HASH_SIZE]; struct dir_hash_node *next; }; // Returns true if the digest of all partial matched contexts is the same as the one // saved by setxattr. Otherwise returns false and constructs a dir_hash_node with the // newly calculated digest. static bool check_context_match_for_dir(const char *pathname, struct dir_hash_node **new_node, bool force, int error) { uint8_t read_digest[SHA1_HASH_SIZE]; ssize_t read_size = getxattr(pathname, RESTORECON_PARTIAL_MATCH_DIGEST, read_digest, SHA1_HASH_SIZE); uint8_t calculated_digest[SHA1_HASH_SIZE]; bool status = selabel_hash_all_partial_matches(fc_sehandle, pathname, calculated_digest); if (!new_node) { return false; } *new_node = NULL; if (!force && status && read_size == SHA1_HASH_SIZE && memcmp(read_digest, calculated_digest, SHA1_HASH_SIZE) == 0) { return true; } // Save the digest of all matched contexts for the current directory. if (!error && status) { *new_node = calloc(1, sizeof(struct dir_hash_node)); if (*new_node == NULL) { selinux_log(SELINUX_ERROR, "SELinux: %s: Out of memory\n", __func__); return false; } (*new_node)->path = strdup(pathname); if ((*new_node)->path == NULL) { selinux_log(SELINUX_ERROR, "SELinux: %s: Out of memory\n", __func__); free(*new_node); *new_node = NULL; return false; } memcpy((*new_node)->digest, calculated_digest, SHA1_HASH_SIZE); (*new_node)->next = NULL; } return false; } static int selinux_android_restorecon_common(const char* pathname_orig, const char *seinfo, uid_t uid, unsigned int flags) { bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false; bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false; bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false; bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false; bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false; bool skipce = (flags & SELINUX_ANDROID_RESTORECON_SKIPCE) ? true : false; bool cross_filesystems = (flags & SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS) ? true : false; bool setrestoreconlast = (flags & SELINUX_ANDROID_RESTORECON_SKIP_SEHASH) ? false : true; bool issys; struct stat sb; struct statfs sfsb; FTS *fts; FTSENT *ftsent; char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname; char * paths[2] = { NULL , NULL }; int ftsflags = FTS_NOCHDIR | FTS_PHYSICAL; int error, sverrno; struct dir_hash_node *current = NULL; struct dir_hash_node *head = NULL; if (!cross_filesystems) { ftsflags |= FTS_XDEV; } if (is_selinux_enabled() <= 0) return 0; __selinux_once(fc_once, file_context_init); if (!fc_sehandle) return 0; /* * Convert passed-in pathname to canonical pathname by resolving realpath of * containing dir, then appending last component name. */ pathbname = basename(pathname_orig); if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) { pathname = realpath(pathname_orig, NULL); if (!pathname) goto realpatherr; } else { pathdname = dirname(pathname_orig); pathdnamer = realpath(pathdname, NULL); if (!pathdnamer) goto realpatherr; if (!strcmp(pathdnamer, "/")) error = asprintf(&pathname, "/%s", pathbname); else error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname); if (error < 0) goto oom; } paths[0] = pathname; issys = (!strcmp(pathname, SYS_PATH) || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false; if (!recurse) { if (lstat(pathname, &sb) < 0) { error = -1; goto cleanup; } error = restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid); goto cleanup; } /* * Ignore saved partial match digest on /data/data or /data/user * since their labeling is based on seapp_contexts and seinfo * assignments rather than file_contexts and is managed by * installd rather than init. */ if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) || !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) setrestoreconlast = false; /* Also ignore on /sys since it is regenerated on each boot regardless. */ if (issys) setrestoreconlast = false; /* Ignore files on in-memory filesystems */ if (statfs(pathname, &sfsb) == 0) { if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) setrestoreconlast = false; } fts = fts_open(paths, ftsflags, NULL); if (!fts) { error = -1; goto cleanup; } error = 0; while ((ftsent = fts_read(fts)) != NULL) { switch (ftsent->fts_info) { case FTS_DC: selinux_log(SELINUX_ERROR, "SELinux: Directory cycle on %s.\n", ftsent->fts_path); errno = ELOOP; error = -1; goto out; case FTS_DP: continue; case FTS_DNR: selinux_log(SELINUX_ERROR, "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_NS: selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_ERR: selinux_log(SELINUX_ERROR, "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_D: if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) { fts_set(fts, ftsent, FTS_SKIP); continue; } if (setrestoreconlast) { struct dir_hash_node* new_node = NULL; if (check_context_match_for_dir(ftsent->fts_path, &new_node, force, error)) { selinux_log(SELINUX_INFO, "SELinux: Skipping restorecon on directory(%s)\n", ftsent->fts_path); fts_set(fts, ftsent, FTS_SKIP); continue; } if (new_node) { if (!current) { current = new_node; head = current; } else { current->next = new_node; current = current->next; } } } if (skipce && (!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PREFIX, sizeof(DATA_SYSTEM_CE_PREFIX)-1) || !strncmp(ftsent->fts_path, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1) || !strncmp(ftsent->fts_path, DATA_VENDOR_CE_PREFIX, sizeof(DATA_VENDOR_CE_PREFIX)-1))) { // Don't label anything below this directory. fts_set(fts, ftsent, FTS_SKIP); // but fall through and make sure we label the directory itself } if (!datadata && (!strcmp(ftsent->fts_path, DATA_DATA_PATH) || !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || !strncmp(ftsent->fts_path, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || !fnmatch(EXPAND_USER_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME) || !fnmatch(EXPAND_USER_DE_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME))) { // Don't label anything below this directory. fts_set(fts, ftsent, FTS_SKIP); // but fall through and make sure we label the directory itself } /* fall through */ default: error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid); break; } } // Labeling successful. Write the partial match digests for subdirectories. // TODO: Write the digest upon FTS_DP if no error occurs in its descents. if (setrestoreconlast && !nochange && !error) { current = head; while (current != NULL) { if (setxattr(current->path, RESTORECON_PARTIAL_MATCH_DIGEST, current->digest, SHA1_HASH_SIZE, 0) < 0) { selinux_log(SELINUX_ERROR, "SELinux: setxattr failed: %s: %s\n", current->path, strerror(errno)); } current = current->next; } } out: sverrno = errno; (void) fts_close(fts); errno = sverrno; cleanup: free(pathdnamer); free(pathname); current = head; while (current != NULL) { struct dir_hash_node *next = current->next; free(current->path); free(current); current = next; } return error; oom: sverrno = errno; selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); errno = sverrno; error = -1; goto cleanup; realpatherr: sverrno = errno; selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n", pathname_orig, strerror(errno)); errno = sverrno; error = -1; goto cleanup; } int selinux_android_restorecon(const char *file, unsigned int flags) { return selinux_android_restorecon_common(file, NULL, -1, flags); } int selinux_android_restorecon_pkgdir(const char *pkgdir, const char *seinfo, uid_t uid, unsigned int flags) { return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA); } void selinux_android_set_sehandle(const struct selabel_handle *hndl) { fc_sehandle = (struct selabel_handle *) hndl; } int selinux_android_load_policy() { int fd = -1; fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); if (fd < 0) { selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n", sepolicy_file, strerror(errno)); return -1; } int ret = selinux_android_load_policy_from_fd(fd, sepolicy_file); close(fd); return ret; } int selinux_android_load_policy_from_fd(int fd, const char *description) { int rc; struct stat sb; void *map = NULL; static int load_successful = 0; /* * Since updating policy at runtime has been abolished * we just check whether a policy has been loaded before * and return if this is the case. * There is no point in reloading policy. */ if (load_successful){ selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n"); return 0; } set_selinuxmnt(SELINUXMNT); if (fstat(fd, &sb) < 0) { selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", description, strerror(errno)); return -1; } map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", description, strerror(errno)); return -1; } rc = security_load_policy(map, sb.st_size); if (rc < 0) { selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n", strerror(errno)); munmap(map, sb.st_size); return -1; } munmap(map, sb.st_size); selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", description); load_successful = 1; return 0; } libselinux/src/android/android_vendor.c0100644 0000000 0000000 00000000753 13756670063 017355 0ustar000000000 0000000 #include "android_common.h" int selinux_android_restorecon(const char *file __attribute__((unused)), unsigned int flags __attribute__((unused))) { selinux_log(SELINUX_ERROR, "%s: not implemented for vendor variant of libselinux\n", __FUNCTION__); return -1; } struct selabel_handle* selinux_android_prop_context_handle(void) { selinux_log(SELINUX_ERROR, "%s: not implemented for vendor variant of libselinux\n", __FUNCTION__); return NULL; } libselinux/src/audit2why.c0100644 0000000 0000000 00000027222 13756670063 014660 0ustar000000000 0000000 /* Workaround for http://bugs.python.org/issue4835 */ #ifndef SIZEOF_SOCKET_T #define SIZEOF_SOCKET_T SIZEOF_INT #endif #include #include #include #include #include #include #include #include #include #include #include #define UNKNOWN -1 #define BADSCON -2 #define BADTCON -3 #define BADTCLASS -4 #define BADPERM -5 #define BADCOMPUTE -6 #define NOPOLICY -7 #define ALLOW 0 #define DONTAUDIT 1 #define TERULE 2 #define BOOLEAN 3 #define CONSTRAINT 4 #define RBAC 5 #define BOUNDS 6 struct boolean_t { char *name; int active; }; static struct boolean_t **boollist = NULL; static int boolcnt = 0; struct avc_t { sepol_handle_t *handle; sepol_policydb_t *policydb; sepol_security_id_t ssid; sepol_security_id_t tsid; sepol_security_class_t tclass; sepol_access_vector_t av; }; static struct avc_t *avc = NULL; static sidtab_t sidtab; static int load_booleans(const sepol_bool_t * boolean, void *arg __attribute__ ((__unused__))) { boollist[boolcnt] = malloc(sizeof(struct boolean_t)); boollist[boolcnt]->name = strdup(sepol_bool_get_name(boolean)); boollist[boolcnt]->active = sepol_bool_get_value(boolean); boolcnt++; return 0; } static int check_booleans(struct boolean_t **bools) { char errormsg[PATH_MAX]; struct sepol_av_decision avd; unsigned int reason; int rc; int i; sepol_bool_key_t *key = NULL; sepol_bool_t *boolean = NULL; int fcnt = 0; int *foundlist = calloc(boolcnt, sizeof(int)); if (!foundlist) { PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); return fcnt; } for (i = 0; i < boolcnt; i++) { char *name = boollist[i]->name; int active = boollist[i]->active; rc = sepol_bool_key_create(avc->handle, name, &key); if (rc < 0) { PyErr_SetString( PyExc_RuntimeError, "Could not create boolean key.\n"); break; } rc = sepol_bool_query(avc->handle, avc->policydb, key, &boolean); if (rc < 0) { snprintf(errormsg, sizeof(errormsg), "Could not find boolean %s.\n", name); PyErr_SetString( PyExc_RuntimeError, errormsg); break; } sepol_bool_set_value(boolean, !active); rc = sepol_bool_set(avc->handle, avc->policydb, key, boolean); if (rc < 0) { snprintf(errormsg, sizeof(errormsg), "Could not set boolean data %s.\n", name); PyErr_SetString( PyExc_RuntimeError, errormsg); break; } /* Reproduce the computation. */ rc = sepol_compute_av_reason(avc->ssid, avc->tsid, avc->tclass, avc->av, &avd, &reason); if (rc < 0) { snprintf(errormsg, sizeof(errormsg), "Error during access vector computation, skipping..."); PyErr_SetString( PyExc_RuntimeError, errormsg); sepol_bool_free(boolean); break; } else { if (!reason) { foundlist[fcnt] = i; fcnt++; } sepol_bool_set_value(boolean, active); rc = sepol_bool_set(avc->handle, avc->policydb, key, boolean); if (rc < 0) { snprintf(errormsg, sizeof(errormsg), "Could not set boolean data %s.\n", name); PyErr_SetString( PyExc_RuntimeError, errormsg); break; } } sepol_bool_free(boolean); sepol_bool_key_free(key); key = NULL; boolean = NULL; } if (key) sepol_bool_key_free(key); if (boolean) sepol_bool_free(boolean); if (fcnt > 0) { *bools = calloc(sizeof(struct boolean_t), fcnt + 1); struct boolean_t *b = *bools; for (i = 0; i < fcnt; i++) { int ctr = foundlist[i]; b[i].name = strdup(boollist[ctr]->name); b[i].active = !boollist[ctr]->active; } } free(foundlist); return fcnt; } static PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) { PyObject *result = 0; if (PyArg_ParseTuple(args,(char *)":finish")) { int i = 0; if (! avc) Py_RETURN_NONE; for (i = 0; i < boolcnt; i++) { free(boollist[i]->name); free(boollist[i]); } free(boollist); sepol_sidtab_shutdown(&sidtab); sepol_sidtab_destroy(&sidtab); sepol_policydb_free(avc->policydb); sepol_handle_destroy(avc->handle); free(avc); avc = NULL; boollist = NULL; boolcnt = 0; /* Boilerplate to return "None" */ Py_RETURN_NONE; } return result; } static int __policy_init(const char *init_path) { FILE *fp; char path[PATH_MAX]; char errormsg[PATH_MAX+1024+20]; struct sepol_policy_file *pf = NULL; int rc; unsigned int cnt; path[PATH_MAX-1] = '\0'; if (init_path) { strncpy(path, init_path, PATH_MAX-1); fp = fopen(path, "re"); if (!fp) { snprintf(errormsg, sizeof(errormsg), "unable to open %s: %s\n", path, strerror(errno)); PyErr_SetString( PyExc_ValueError, errormsg); return 1; } } else { const char *curpolicy = selinux_current_policy_path(); if (!curpolicy) { /* SELinux disabled, must use -p option. */ snprintf(errormsg, sizeof(errormsg), "You must specify the -p option with the path to the policy file.\n"); PyErr_SetString( PyExc_ValueError, errormsg); return 1; } fp = fopen(curpolicy, "re"); if (!fp) { snprintf(errormsg, sizeof(errormsg), "unable to open %s: %s\n", curpolicy, strerror(errno)); PyErr_SetString( PyExc_ValueError, errormsg); return 1; } } avc = calloc(sizeof(struct avc_t), 1); if (!avc) { PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); fclose(fp); return 1; } /* Set up a policydb directly so that we can mutate it later for testing what booleans might have allowed the access. Otherwise, we'd just use sepol_set_policydb_from_file() here. */ if (sepol_policy_file_create(&pf) || sepol_policydb_create(&avc->policydb)) { snprintf(errormsg, sizeof(errormsg), "policydb_init failed: %s\n", strerror(errno)); PyErr_SetString( PyExc_RuntimeError, errormsg); fclose(fp); return 1; } sepol_policy_file_set_fp(pf, fp); if (sepol_policydb_read(avc->policydb, pf)) { snprintf(errormsg, sizeof(errormsg), "invalid binary policy %s\n", path); PyErr_SetString( PyExc_ValueError, errormsg); fclose(fp); return 1; } fclose(fp); sepol_set_policydb(&avc->policydb->p); avc->handle = sepol_handle_create(); /* Turn off messages */ sepol_msg_set_callback(avc->handle, NULL, NULL); rc = sepol_bool_count(avc->handle, avc->policydb, &cnt); if (rc < 0) { PyErr_SetString( PyExc_RuntimeError, "unable to get bool count\n"); return 1; } boollist = calloc(cnt, sizeof(*boollist)); if (!boollist) { PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); return 1; } sepol_bool_iterate(avc->handle, avc->policydb, load_booleans, (void *)NULL); /* Initialize the sidtab for subsequent use by sepol_context_to_sid and sepol_compute_av_reason. */ rc = sepol_sidtab_init(&sidtab); if (rc < 0) { PyErr_SetString( PyExc_RuntimeError, "unable to init sidtab\n"); free(boollist); return 1; } sepol_set_sidtab(&sidtab); return 0; } static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { int result; char *init_path=NULL; if (avc) { PyErr_SetString( PyExc_RuntimeError, "init called multiple times"); return NULL; } if (!PyArg_ParseTuple(args,(char *)"|s:policy_init",&init_path)) return NULL; result = __policy_init(init_path); return Py_BuildValue("i", result); } #define RETURN(X) \ { \ return Py_BuildValue("iO", (X), Py_None); \ } static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) { char *reason_buf = NULL; char * scon; char * tcon; char *tclassstr; PyObject *listObj; PyObject *strObj; int numlines; struct boolean_t *bools; unsigned int reason; sepol_security_id_t ssid, tsid; sepol_security_class_t tclass; sepol_access_vector_t perm, av; struct sepol_av_decision avd; int rc; int i=0; if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj)) return NULL; /* get the number of lines passed to us */ numlines = PyList_Size(listObj); /* should raise an error here. */ if (numlines < 0) return NULL; /* Not a list */ if (!avc) RETURN(NOPOLICY) rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid); if (rc < 0) RETURN(BADSCON) rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (rc < 0) RETURN(BADTCON) rc = sepol_string_to_security_class(tclassstr, &tclass); if (rc < 0) RETURN(BADTCLASS) /* Convert the permission list to an AV. */ av = 0; /* iterate over items of the list, grabbing strings, and parsing for numbers */ for (i=0; i= 3 permstr = _PyUnicode_AsString( strObj ); #else permstr = PyString_AsString( strObj ); #endif rc = sepol_string_to_av_perm(tclass, permstr, &perm); if (rc < 0) RETURN(BADPERM) av |= perm; } /* Reproduce the computation. */ rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0); if (rc < 0) RETURN(BADCOMPUTE) if (!reason) RETURN(ALLOW) if (reason & SEPOL_COMPUTEAV_TE) { avc->ssid = ssid; avc->tsid = tsid; avc->tclass = tclass; avc->av = av; if (check_booleans(&bools) == 0) { if (av & ~avd.auditdeny) { RETURN(DONTAUDIT) } else { RETURN(TERULE) } } else { PyObject *outboollist; struct boolean_t *b = bools; int len=0; while (b->name) { len++; b++; } b = bools; outboollist = PyList_New(len); len=0; while(b->name) { PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active); PyList_SetItem(outboollist, len++, bool_); b++; } free(bools); /* 'N' steals the reference to outboollist */ return Py_BuildValue("iN", BOOLEAN, outboollist); } } if (reason & SEPOL_COMPUTEAV_CONS) { if (reason_buf) { PyObject *result = NULL; result = Py_BuildValue("is", CONSTRAINT, reason_buf); free(reason_buf); return result; } RETURN(CONSTRAINT) } if (reason & SEPOL_COMPUTEAV_RBAC) RETURN(RBAC) if (reason & SEPOL_COMPUTEAV_BOUNDS) RETURN(BOUNDS) RETURN(BADCOMPUTE) } static PyMethodDef audit2whyMethods[] = { {"init", init, METH_VARARGS, "Initialize policy database."}, {"analyze", analyze, METH_VARARGS, "Analyze AVC."}, {"finish", finish, METH_VARARGS, "Finish using policy, free memory."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 /* Module-initialization logic specific to Python 3 */ static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "audit2why", NULL, 0, audit2whyMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_audit2why(void); /* silence -Wmissing-prototypes */ PyMODINIT_FUNC PyInit_audit2why(void) #else PyMODINIT_FUNC initaudit2why(void); /* silence -Wmissing-prototypes */ PyMODINIT_FUNC initaudit2why(void) #endif { PyObject *m; #if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); if (m == NULL) { return NULL; } #else m = Py_InitModule("audit2why", audit2whyMethods); #endif PyModule_AddIntConstant(m,"UNKNOWN", UNKNOWN); PyModule_AddIntConstant(m,"BADSCON", BADSCON); PyModule_AddIntConstant(m,"BADTCON", BADTCON); PyModule_AddIntConstant(m,"BADTCLASS", BADTCLASS); PyModule_AddIntConstant(m,"BADPERM", BADPERM); PyModule_AddIntConstant(m,"BADCOMPUTE", BADCOMPUTE); PyModule_AddIntConstant(m,"NOPOLICY", NOPOLICY); PyModule_AddIntConstant(m,"ALLOW", ALLOW); PyModule_AddIntConstant(m,"DONTAUDIT", DONTAUDIT); PyModule_AddIntConstant(m,"TERULE", TERULE); PyModule_AddIntConstant(m,"BOOLEAN", BOOLEAN); PyModule_AddIntConstant(m,"CONSTRAINT", CONSTRAINT); PyModule_AddIntConstant(m,"RBAC", RBAC); PyModule_AddIntConstant(m,"BOUNDS", BOUNDS); #if PY_MAJOR_VERSION >= 3 return m; #endif } libselinux/src/audit2why.map0100644 0000000 0000000 00000000122 13756670063 015201 0ustar000000000 0000000 AUDIT2WHY_2.9 { global: initaudit2why; PyInit_audit2why; local: *; }; libselinux/src/avc.c0100644 0000000 0000000 00000065103 13756670063 013511 0ustar000000000 0000000 /* * Implementation of the userspace access vector cache (AVC). * * Author : Eamon Walsh * * Derived from the kernel AVC implementation by * Stephen Smalley and * James Morris . */ #include #include "selinux_internal.h" #include #include "avc_sidtab.h" #include "avc_internal.h" #define AVC_CACHE_SLOTS 512 #define AVC_CACHE_MAXNODES 410 struct avc_entry { security_id_t ssid; security_id_t tsid; security_class_t tclass; struct av_decision avd; security_id_t create_sid; int used; /* used recently */ }; struct avc_node { struct avc_entry ae; struct avc_node *next; }; struct avc_cache { struct avc_node *slots[AVC_CACHE_SLOTS]; uint32_t lru_hint; /* LRU hint for reclaim scan */ uint32_t active_nodes; uint32_t latest_notif; /* latest revocation notification */ }; struct avc_callback_node { int (*callback) (uint32_t event, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, access_vector_t * out_retained); uint32_t events; security_id_t ssid; security_id_t tsid; security_class_t tclass; access_vector_t perms; struct avc_callback_node *next; }; static void *avc_netlink_thread = NULL; static void *avc_lock = NULL; static void *avc_log_lock = NULL; static struct avc_node *avc_node_freelist = NULL; static struct avc_cache avc_cache; static char *avc_audit_buf = NULL; static struct avc_cache_stats cache_stats; static struct avc_callback_node *avc_callbacks = NULL; static struct sidtab avc_sidtab; static inline int avc_hash(security_id_t ssid, security_id_t tsid, security_class_t tclass) { return ((uintptr_t) ssid ^ ((uintptr_t) tsid << 2) ^ tclass) & (AVC_CACHE_SLOTS - 1); } int avc_context_to_sid_raw(const char * ctx, security_id_t * sid) { int rc; /* avc_init needs to be called before this function */ assert(avc_running); avc_get_lock(avc_lock); rc = sidtab_context_to_sid(&avc_sidtab, ctx, sid); avc_release_lock(avc_lock); return rc; } int avc_context_to_sid(const char * ctx, security_id_t * sid) { int ret; char * rctx; if (selinux_trans_to_raw_context(ctx, &rctx)) return -1; ret = avc_context_to_sid_raw(rctx, sid); freecon(rctx); return ret; } int avc_sid_to_context_raw(security_id_t sid, char ** ctx) { int rc; *ctx = NULL; avc_get_lock(avc_lock); *ctx = strdup(sid->ctx); /* caller must free via freecon */ rc = *ctx ? 0 : -1; avc_release_lock(avc_lock); return rc; } int avc_sid_to_context(security_id_t sid, char ** ctx) { int ret; char * rctx; ret = avc_sid_to_context_raw(sid, &rctx); if (ret == 0) { ret = selinux_raw_to_trans_context(rctx, ctx); freecon(rctx); } return ret; } int sidget(security_id_t sid __attribute__((unused))) { return 1; } int sidput(security_id_t sid __attribute__((unused))) { return 1; } int avc_get_initial_sid(const char * name, security_id_t * sid) { int rc; char * con; rc = security_get_initial_context_raw(name, &con); if (rc < 0) return rc; rc = avc_context_to_sid_raw(con, sid); freecon(con); return rc; } int avc_open(struct selinux_opt *opts, unsigned nopts) { avc_setenforce = 0; while (nopts--) switch(opts[nopts].type) { case AVC_OPT_SETENFORCE: avc_setenforce = 1; avc_enforcing = !!opts[nopts].value; break; } return avc_init("avc", NULL, NULL, NULL, NULL); } int avc_init(const char *prefix, const struct avc_memory_callback *mem_cb, const struct avc_log_callback *log_cb, const struct avc_thread_callback *thread_cb, const struct avc_lock_callback *lock_cb) { struct avc_node *new; int i, rc = 0; if (avc_running) return 0; if (prefix) strncpy(avc_prefix, prefix, AVC_PREFIX_SIZE - 1); set_callbacks(mem_cb, log_cb, thread_cb, lock_cb); avc_lock = avc_alloc_lock(); avc_log_lock = avc_alloc_lock(); memset(&cache_stats, 0, sizeof(cache_stats)); for (i = 0; i < AVC_CACHE_SLOTS; i++) avc_cache.slots[i] = 0; avc_cache.lru_hint = 0; avc_cache.active_nodes = 0; avc_cache.latest_notif = 0; rc = sidtab_init(&avc_sidtab); if (rc) { avc_log(SELINUX_ERROR, "%s: unable to initialize SID table\n", avc_prefix); goto out; } avc_audit_buf = (char *)avc_malloc(AVC_AUDIT_BUFSIZE); if (!avc_audit_buf) { avc_log(SELINUX_ERROR, "%s: unable to allocate audit buffer\n", avc_prefix); rc = -1; goto out; } for (i = 0; i < AVC_CACHE_MAXNODES; i++) { new = avc_malloc(sizeof(*new)); if (!new) { avc_log(SELINUX_WARNING, "%s: warning: only got %d av entries\n", avc_prefix, i); break; } memset(new, 0, sizeof(*new)); new->next = avc_node_freelist; avc_node_freelist = new; } if (!avc_setenforce) { rc = security_getenforce(); if (rc < 0) { avc_log(SELINUX_ERROR, "%s: could not determine enforcing mode: %s\n", avc_prefix, strerror(errno)); goto out; } avc_enforcing = rc; } rc = avc_netlink_open(0); if (rc < 0) { avc_log(SELINUX_ERROR, "%s: can't open netlink socket: %d (%s)\n", avc_prefix, errno, strerror(errno)); goto out; } if (avc_using_threads) { avc_netlink_thread = avc_create_thread(&avc_netlink_loop); avc_netlink_trouble = 0; } avc_running = 1; out: return rc; } void avc_cache_stats(struct avc_cache_stats *p) { memcpy(p, &cache_stats, sizeof(cache_stats)); } void avc_sid_stats(void) { /* avc_init needs to be called before this function */ assert(avc_running); avc_get_lock(avc_log_lock); avc_get_lock(avc_lock); sidtab_sid_stats(&avc_sidtab, avc_audit_buf, AVC_AUDIT_BUFSIZE); avc_release_lock(avc_lock); avc_log(SELINUX_INFO, "%s", avc_audit_buf); avc_release_lock(avc_log_lock); } void avc_av_stats(void) { int i, chain_len, max_chain_len, slots_used; struct avc_node *node; avc_get_lock(avc_lock); slots_used = 0; max_chain_len = 0; for (i = 0; i < AVC_CACHE_SLOTS; i++) { node = avc_cache.slots[i]; if (node) { slots_used++; chain_len = 0; while (node) { chain_len++; node = node->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } avc_release_lock(avc_lock); avc_log(SELINUX_INFO, "%s: %u AV entries and %d/%d buckets used, " "longest chain length %d\n", avc_prefix, avc_cache.active_nodes, slots_used, AVC_CACHE_SLOTS, max_chain_len); } hidden_def(avc_av_stats) static inline struct avc_node *avc_reclaim_node(void) { struct avc_node *prev, *cur; int try; uint32_t hvalue; hvalue = avc_cache.lru_hint; for (try = 0; try < 2; try++) { do { prev = NULL; cur = avc_cache.slots[hvalue]; while (cur) { if (!cur->ae.used) goto found; cur->ae.used = 0; prev = cur; cur = cur->next; } hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1); } while (hvalue != avc_cache.lru_hint); } errno = ENOMEM; /* this was a panic in the kernel... */ return NULL; found: avc_cache.lru_hint = hvalue; if (prev == NULL) avc_cache.slots[hvalue] = cur->next; else prev->next = cur->next; return cur; } static inline void avc_clear_avc_entry(struct avc_entry *ae) { memset(ae, 0, sizeof(*ae)); } static inline struct avc_node *avc_claim_node(security_id_t ssid, security_id_t tsid, security_class_t tclass) { struct avc_node *new; int hvalue; if (!avc_node_freelist) avc_cleanup(); if (avc_node_freelist) { new = avc_node_freelist; avc_node_freelist = avc_node_freelist->next; avc_cache.active_nodes++; } else { new = avc_reclaim_node(); if (!new) goto out; } hvalue = avc_hash(ssid, tsid, tclass); avc_clear_avc_entry(&new->ae); new->ae.used = 1; new->ae.ssid = ssid; new->ae.tsid = tsid; new->ae.tclass = tclass; new->next = avc_cache.slots[hvalue]; avc_cache.slots[hvalue] = new; out: return new; } static inline struct avc_node *avc_search_node(security_id_t ssid, security_id_t tsid, security_class_t tclass, int *probes) { struct avc_node *cur; int hvalue; int tprobes = 1; hvalue = avc_hash(ssid, tsid, tclass); cur = avc_cache.slots[hvalue]; while (cur != NULL && (ssid != cur->ae.ssid || tclass != cur->ae.tclass || tsid != cur->ae.tsid)) { tprobes++; cur = cur->next; } if (cur == NULL) { /* cache miss */ goto out; } /* cache hit */ if (probes) *probes = tprobes; cur->ae.used = 1; out: return cur; } /** * avc_lookup - Look up an AVC entry. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @aeref: AVC entry reference * * Look up an AVC entry that is valid for the * @requested permissions between the SID pair * (@ssid, @tsid), interpreting the permissions * based on @tclass. If a valid AVC entry exists, * then this function updates @aeref to refer to the * entry and returns %0. Otherwise, -1 is returned. */ static int avc_lookup(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct avc_entry_ref *aeref) { struct avc_node *node; int probes, rc = 0; avc_cache_stats_incr(cav_lookups); node = avc_search_node(ssid, tsid, tclass, &probes); if (node && ((node->ae.avd.decided & requested) == requested)) { avc_cache_stats_incr(cav_hits); avc_cache_stats_add(cav_probes, probes); aeref->ae = &node->ae; goto out; } avc_cache_stats_incr(cav_misses); rc = -1; out: return rc; } /** * avc_insert - Insert an AVC entry. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @ae: AVC entry * @aeref: AVC entry reference * * Insert an AVC entry for the SID pair * (@ssid, @tsid) and class @tclass. * The access vectors and the sequence number are * normally provided by the security server in * response to a security_compute_av() call. If the * sequence number @ae->avd.seqno is not less than the latest * revocation notification, then the function copies * the access vectors into a cache entry, updates * @aeref to refer to the entry, and returns %0. * Otherwise, this function returns -%1 with @errno set to %EAGAIN. */ static int avc_insert(security_id_t ssid, security_id_t tsid, security_class_t tclass, struct avc_entry *ae, struct avc_entry_ref *aeref) { struct avc_node *node; int rc = 0; if (ae->avd.seqno < avc_cache.latest_notif) { avc_log(SELINUX_WARNING, "%s: seqno %u < latest_notif %u\n", avc_prefix, ae->avd.seqno, avc_cache.latest_notif); errno = EAGAIN; rc = -1; goto out; } node = avc_claim_node(ssid, tsid, tclass); if (!node) { rc = -1; goto out; } memcpy(&node->ae.avd, &ae->avd, sizeof(ae->avd)); aeref->ae = &node->ae; out: return rc; } void avc_cleanup(void) { } hidden_def(avc_cleanup) int avc_reset(void) { struct avc_callback_node *c; int i, ret, rc = 0, errsave = 0; struct avc_node *node, *tmp; errno = 0; if (!avc_running) return 0; avc_get_lock(avc_lock); for (i = 0; i < AVC_CACHE_SLOTS; i++) { node = avc_cache.slots[i]; while (node) { tmp = node; node = node->next; avc_clear_avc_entry(&tmp->ae); tmp->next = avc_node_freelist; avc_node_freelist = tmp; avc_cache.active_nodes--; } avc_cache.slots[i] = 0; } avc_cache.lru_hint = 0; avc_release_lock(avc_lock); memset(&cache_stats, 0, sizeof(cache_stats)); for (c = avc_callbacks; c; c = c->next) { if (c->events & AVC_CALLBACK_RESET) { ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0); if (ret && !rc) { rc = ret; errsave = errno; } } } errno = errsave; return rc; } hidden_def(avc_reset) void avc_destroy(void) { struct avc_callback_node *c; struct avc_node *node, *tmp; int i; /* avc_init needs to be called before this function */ assert(avc_running); avc_get_lock(avc_lock); if (avc_using_threads) avc_stop_thread(avc_netlink_thread); avc_netlink_close(); for (i = 0; i < AVC_CACHE_SLOTS; i++) { node = avc_cache.slots[i]; while (node) { tmp = node; node = node->next; avc_free(tmp); } } while (avc_node_freelist) { tmp = avc_node_freelist; avc_node_freelist = tmp->next; avc_free(tmp); } avc_release_lock(avc_lock); while (avc_callbacks) { c = avc_callbacks; avc_callbacks = c->next; avc_free(c); } sidtab_destroy(&avc_sidtab); avc_free_lock(avc_lock); avc_free_lock(avc_log_lock); avc_free(avc_audit_buf); avc_running = 0; } /* ratelimit stuff put aside for now --EFW */ #if 0 /* * Copied from net/core/utils.c:net_ratelimit and modified for * use by the AVC audit facility. */ #define AVC_MSG_COST 5*HZ #define AVC_MSG_BURST 10*5*HZ /* * This enforces a rate limit: not more than one kernel message * every 5secs to make a denial-of-service attack impossible. */ static int avc_ratelimit(void) { static unsigned long toks = 10 * 5 * HZ; static unsigned long last_msg; static int missed, rc = 0; unsigned long now = jiffies; void *ratelimit_lock = avc_alloc_lock(); avc_get_lock(ratelimit_lock); toks += now - last_msg; last_msg = now; if (toks > AVC_MSG_BURST) toks = AVC_MSG_BURST; if (toks >= AVC_MSG_COST) { int lost = missed; missed = 0; toks -= AVC_MSG_COST; avc_release_lock(ratelimit_lock); if (lost) { avc_log(SELINUX_WARNING, "%s: %d messages suppressed.\n", avc_prefix, lost); } rc = 1; goto out; } missed++; avc_release_lock(ratelimit_lock); out: avc_free_lock(ratelimit_lock); return rc; } static inline int check_avc_ratelimit(void) { if (avc_enforcing) return avc_ratelimit(); else { /* If permissive, then never suppress messages. */ return 1; } } #endif /* ratelimit stuff */ /** * avc_dump_av - Display an access vector in human-readable form. * @tclass: target security class * @av: access vector */ static void avc_dump_av(security_class_t tclass, access_vector_t av) { const char *permstr; access_vector_t bit = 1; if (av == 0) { log_append(avc_audit_buf, " null"); return; } log_append(avc_audit_buf, " {"); while (av) { if (av & bit) { permstr = security_av_perm_to_string(tclass, bit); if (!permstr) break; log_append(avc_audit_buf, " %s", permstr); av &= ~bit; } bit <<= 1; } if (av) log_append(avc_audit_buf, " 0x%x", av); log_append(avc_audit_buf, " }"); } /** * avc_dump_query - Display a SID pair and a class in human-readable form. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class */ static void avc_dump_query(security_id_t ssid, security_id_t tsid, security_class_t tclass) { avc_get_lock(avc_lock); log_append(avc_audit_buf, "scontext=%s tcontext=%s", ssid->ctx, tsid->ctx); avc_release_lock(avc_lock); log_append(avc_audit_buf, " tclass=%s", security_class_to_string(tclass)); } void avc_audit(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct av_decision *avd, int result, void *a) { access_vector_t denied, audited; denied = requested & ~avd->allowed; if (denied) audited = denied & avd->auditdeny; else if (!requested || result) audited = denied = requested; else audited = requested & avd->auditallow; if (!audited) return; #if 0 if (!check_avc_ratelimit()) return; #endif /* prevent overlapping buffer writes */ avc_get_lock(avc_log_lock); snprintf(avc_audit_buf, AVC_AUDIT_BUFSIZE, "%s: %s ", avc_prefix, (denied || !requested) ? "denied" : "granted"); avc_dump_av(tclass, audited); log_append(avc_audit_buf, " for "); /* get any extra information printed by the callback */ avc_suppl_audit(a, tclass, avc_audit_buf + strlen(avc_audit_buf), AVC_AUDIT_BUFSIZE - strlen(avc_audit_buf)); log_append(avc_audit_buf, " "); avc_dump_query(ssid, tsid, tclass); if (denied) log_append(avc_audit_buf, " permissive=%u", result ? 0 : 1); log_append(avc_audit_buf, "\n"); avc_log(SELINUX_AVC, "%s", avc_audit_buf); avc_release_lock(avc_log_lock); } hidden_def(avc_audit) static void avd_init(struct av_decision *avd) { avd->allowed = 0; avd->auditallow = 0; avd->auditdeny = 0xffffffff; avd->seqno = avc_cache.latest_notif; avd->flags = 0; } int avc_has_perm_noaudit(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct avc_entry_ref *aeref, struct av_decision *avd) { struct avc_entry *ae; int rc = 0; struct avc_entry entry; access_vector_t denied; struct avc_entry_ref ref; if (avd) avd_init(avd); if (!avc_using_threads && !avc_app_main_loop) { (void)avc_netlink_check_nb(); } if (!aeref) { avc_entry_ref_init(&ref); aeref = &ref; } avc_get_lock(avc_lock); avc_cache_stats_incr(entry_lookups); ae = aeref->ae; if (ae) { if (ae->ssid == ssid && ae->tsid == tsid && ae->tclass == tclass && ((ae->avd.decided & requested) == requested)) { avc_cache_stats_incr(entry_hits); ae->used = 1; } else { avc_cache_stats_incr(entry_discards); ae = 0; } } if (!ae) { avc_cache_stats_incr(entry_misses); rc = avc_lookup(ssid, tsid, tclass, requested, aeref); if (rc) { rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx, tclass, requested, &entry.avd); if (rc && errno == EINVAL && !avc_enforcing) { rc = errno = 0; goto out; } if (rc) goto out; rc = avc_insert(ssid, tsid, tclass, &entry, aeref); if (rc) goto out; } ae = aeref->ae; } if (avd) memcpy(avd, &ae->avd, sizeof(*avd)); denied = requested & ~(ae->avd.allowed); if (!requested || denied) { if (!avc_enforcing || (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE)) ae->avd.allowed |= requested; else { errno = EACCES; rc = -1; } } out: avc_release_lock(avc_lock); return rc; } hidden_def(avc_has_perm_noaudit) int avc_has_perm(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t requested, struct avc_entry_ref *aeref, void *auditdata) { struct av_decision avd; int errsave, rc; rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd); errsave = errno; avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); errno = errsave; return rc; } int avc_compute_create(security_id_t ssid, security_id_t tsid, security_class_t tclass, security_id_t *newsid) { int rc; struct avc_entry_ref aeref; struct avc_entry entry; char * ctx; *newsid = NULL; avc_entry_ref_init(&aeref); avc_get_lock(avc_lock); /* check for a cached entry */ rc = avc_lookup(ssid, tsid, tclass, 0, &aeref); if (rc) { /* need to make a cache entry for this tuple */ rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx, tclass, 0, &entry.avd); if (rc) goto out; rc = avc_insert(ssid, tsid, tclass, &entry, &aeref); if (rc) goto out; } /* check for a saved compute_create value */ if (!aeref.ae->create_sid) { /* need to query the kernel policy */ rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass, &ctx); if (rc) goto out; rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid); freecon(ctx); if (rc) goto out; aeref.ae->create_sid = *newsid; } else { /* found saved value */ *newsid = aeref.ae->create_sid; } rc = 0; out: avc_release_lock(avc_lock); return rc; } int avc_compute_member(security_id_t ssid, security_id_t tsid, security_class_t tclass, security_id_t *newsid) { int rc; char * ctx = NULL; *newsid = NULL; /* avc_init needs to be called before this function */ assert(avc_running); avc_get_lock(avc_lock); rc = security_compute_member_raw(ssid->ctx, tsid->ctx, tclass, &ctx); if (rc) goto out; rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid); freecon(ctx); out: avc_release_lock(avc_lock); return rc; } int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, access_vector_t * out_retained), uint32_t events, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms) { struct avc_callback_node *c; int rc = 0; c = avc_malloc(sizeof(*c)); if (!c) { rc = -1; goto out; } c->callback = callback; c->events = events; c->ssid = ssid; c->tsid = tsid; c->tclass = tclass; c->perms = perms; c->next = avc_callbacks; avc_callbacks = c; out: return rc; } static inline int avc_sidcmp(security_id_t x, security_id_t y) { return (x == y || x == SECSID_WILD || y == SECSID_WILD); } static inline void avc_update_node(uint32_t event, struct avc_node *node, access_vector_t perms) { switch (event) { case AVC_CALLBACK_GRANT: node->ae.avd.allowed |= perms; break; case AVC_CALLBACK_TRY_REVOKE: case AVC_CALLBACK_REVOKE: node->ae.avd.allowed &= ~perms; break; case AVC_CALLBACK_AUDITALLOW_ENABLE: node->ae.avd.auditallow |= perms; break; case AVC_CALLBACK_AUDITALLOW_DISABLE: node->ae.avd.auditallow &= ~perms; break; case AVC_CALLBACK_AUDITDENY_ENABLE: node->ae.avd.auditdeny |= perms; break; case AVC_CALLBACK_AUDITDENY_DISABLE: node->ae.avd.auditdeny &= ~perms; break; } } static int avc_update_cache(uint32_t event, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms) { struct avc_node *node; int i; avc_get_lock(avc_lock); if (ssid == SECSID_WILD || tsid == SECSID_WILD) { /* apply to all matching nodes */ for (i = 0; i < AVC_CACHE_SLOTS; i++) { for (node = avc_cache.slots[i]; node; node = node->next) { if (avc_sidcmp(ssid, node->ae.ssid) && avc_sidcmp(tsid, node->ae.tsid) && tclass == node->ae.tclass) { avc_update_node(event, node, perms); } } } } else { /* apply to one node */ node = avc_search_node(ssid, tsid, tclass, 0); if (node) { avc_update_node(event, node, perms); } } avc_release_lock(avc_lock); return 0; } /* avc_control - update cache and call callbacks * * This should not be called directly; use the individual event * functions instead. */ static int avc_control(uint32_t event, security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, access_vector_t * out_retained) { struct avc_callback_node *c; access_vector_t tretained = 0, cretained = 0; int ret, rc = 0, errsave = 0; errno = 0; /* * try_revoke only removes permissions from the cache * state if they are not retained by the object manager. * Hence, try_revoke must wait until after the callbacks have * been invoked to update the cache state. */ if (event != AVC_CALLBACK_TRY_REVOKE) avc_update_cache(event, ssid, tsid, tclass, perms); for (c = avc_callbacks; c; c = c->next) { if ((c->events & event) && avc_sidcmp(c->ssid, ssid) && avc_sidcmp(c->tsid, tsid) && c->tclass == tclass && (c->perms & perms)) { cretained = 0; ret = c->callback(event, ssid, tsid, tclass, (c->perms & perms), &cretained); if (ret && !rc) { rc = ret; errsave = errno; } if (!ret) tretained |= cretained; } } if (event == AVC_CALLBACK_TRY_REVOKE) { /* revoke any unretained permissions */ perms &= ~tretained; avc_update_cache(event, ssid, tsid, tclass, perms); *out_retained = tretained; } avc_get_lock(avc_lock); if (seqno > avc_cache.latest_notif) avc_cache.latest_notif = seqno; avc_release_lock(avc_lock); errno = errsave; return rc; } /** * avc_ss_grant - Grant previously denied permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number */ int avc_ss_grant(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno) { return avc_control(AVC_CALLBACK_GRANT, ssid, tsid, tclass, perms, seqno, 0); } /** * avc_ss_try_revoke - Try to revoke previously granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @out_retained: subset of @perms that are retained * * Try to revoke previously granted permissions, but * only if they are not retained as migrated permissions. * Return the subset of permissions that are retained via @out_retained. */ int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, access_vector_t * out_retained) { return avc_control(AVC_CALLBACK_TRY_REVOKE, ssid, tsid, tclass, perms, seqno, out_retained); } /** * avc_ss_revoke - Revoke previously granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * * Revoke previously granted permissions, even if * they are retained as migrated permissions. */ int avc_ss_revoke(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno) { return avc_control(AVC_CALLBACK_REVOKE, ssid, tsid, tclass, perms, seqno, 0); } /** * avc_ss_reset - Flush the cache and revalidate migrated permissions. * @seqno: policy sequence number */ int avc_ss_reset(uint32_t seqno) { int rc; rc = avc_reset(); avc_get_lock(avc_lock); if (seqno > avc_cache.latest_notif) avc_cache.latest_notif = seqno; avc_release_lock(avc_lock); return rc; } /** * avc_ss_set_auditallow - Enable or disable auditing of granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @enable: enable flag. */ int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, uint32_t enable) { if (enable) return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE, ssid, tsid, tclass, perms, seqno, 0); else return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE, ssid, tsid, tclass, perms, seqno, 0); } /** * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @enable: enable flag. */ int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, uint32_t enable) { if (enable) return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE, ssid, tsid, tclass, perms, seqno, 0); else return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE, ssid, tsid, tclass, perms, seqno, 0); } libselinux/src/avc_internal.c0100644 0000000 0000000 00000013621 13756670063 015403 0ustar000000000 0000000 /* * Callbacks for user-supplied memory allocation, supplemental * auditing, and locking routines. * * Author : Eamon Walsh * * Netlink code derived in part from sample code by * James Morris . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" #include "selinux_netlink.h" #include "avc_internal.h" #ifndef NETLINK_SELINUX #define NETLINK_SELINUX 7 #endif /* callback pointers */ void *(*avc_func_malloc) (size_t) = NULL; void (*avc_func_free) (void *) = NULL; void (*avc_func_log) (const char *, ...) = NULL; void (*avc_func_audit) (void *, security_class_t, char *, size_t) = NULL; int avc_using_threads = 0; int avc_app_main_loop = 0; void *(*avc_func_create_thread) (void (*)(void)) = NULL; void (*avc_func_stop_thread) (void *) = NULL; void *(*avc_func_alloc_lock) (void) = NULL; void (*avc_func_get_lock) (void *) = NULL; void (*avc_func_release_lock) (void *) = NULL; void (*avc_func_free_lock) (void *) = NULL; /* message prefix string and avc enforcing mode */ char avc_prefix[AVC_PREFIX_SIZE] = "uavc"; int avc_running = 0; int avc_enforcing = 1; int avc_setenforce = 0; int avc_netlink_trouble = 0; /* netlink socket code */ static int fd = -1; int avc_netlink_open(int blocking) { int len, rc = 0; struct sockaddr_nl addr; fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_SELINUX); if (fd < 0) { rc = fd; goto out; } if (!blocking && fcntl(fd, F_SETFL, O_NONBLOCK)) { close(fd); fd = -1; rc = -1; goto out; } len = sizeof(addr); memset(&addr, 0, len); addr.nl_family = AF_NETLINK; addr.nl_groups = SELNL_GRP_AVC; if (bind(fd, (struct sockaddr *)&addr, len) < 0) { close(fd); fd = -1; rc = -1; goto out; } out: return rc; } void avc_netlink_close(void) { if (fd >= 0) close(fd); fd = -1; } static int avc_netlink_receive(void *buf, unsigned buflen, int blocking) { int rc; struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 }; struct sockaddr_nl nladdr; socklen_t nladdrlen = sizeof nladdr; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; do { rc = poll(&pfd, 1, (blocking ? -1 : 0)); } while (rc < 0 && errno == EINTR); if (rc == 0 && !blocking) { errno = EWOULDBLOCK; return -1; } else if (rc < 1) { avc_log(SELINUX_ERROR, "%s: netlink poll: error %d\n", avc_prefix, errno); return rc; } rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr, &nladdrlen); if (rc < 0) return rc; if (nladdrlen != sizeof nladdr) { avc_log(SELINUX_WARNING, "%s: warning: netlink address truncated, len %u?\n", avc_prefix, nladdrlen); return -1; } if (nladdr.nl_pid) { avc_log(SELINUX_WARNING, "%s: warning: received spoofed netlink packet from: %u\n", avc_prefix, nladdr.nl_pid); return -1; } if (rc == 0) { avc_log(SELINUX_WARNING, "%s: warning: received EOF on netlink socket\n", avc_prefix); errno = EBADFD; return -1; } if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) { avc_log(SELINUX_WARNING, "%s: warning: incomplete netlink message\n", avc_prefix); return -1; } return 0; } static int avc_netlink_process(void *buf) { int rc; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; switch (nlh->nlmsg_type) { case NLMSG_ERROR:{ struct nlmsgerr *err = NLMSG_DATA(nlh); /* Netlink ack */ if (err->error == 0) break; errno = -err->error; avc_log(SELINUX_ERROR, "%s: netlink error: %d\n", avc_prefix, errno); return -1; } case SELNL_MSG_SETENFORCE:{ struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh); msg->val = !!msg->val; avc_log(SELINUX_INFO, "%s: received setenforce notice (enforcing=%d)\n", avc_prefix, msg->val); if (avc_setenforce) break; avc_enforcing = msg->val; if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) { avc_log(SELINUX_ERROR, "%s: cache reset returned %d (errno %d)\n", avc_prefix, rc, errno); return rc; } rc = selinux_netlink_setenforce(msg->val); if (rc < 0) return rc; break; } case SELNL_MSG_POLICYLOAD:{ struct selnl_msg_policyload *msg = NLMSG_DATA(nlh); avc_log(SELINUX_INFO, "%s: received policyload notice (seqno=%u)\n", avc_prefix, msg->seqno); rc = avc_ss_reset(msg->seqno); if (rc < 0) { avc_log(SELINUX_ERROR, "%s: cache reset returned %d (errno %d)\n", avc_prefix, rc, errno); return rc; } rc = selinux_netlink_policyload(msg->seqno); if (rc < 0) return rc; break; } default: avc_log(SELINUX_WARNING, "%s: warning: unknown netlink message %d\n", avc_prefix, nlh->nlmsg_type); } return 0; } int avc_netlink_check_nb(void) { int rc; char buf[1024] __attribute__ ((aligned)); while (1) { errno = 0; rc = avc_netlink_receive(buf, sizeof(buf), 0); if (rc < 0) { if (errno == EWOULDBLOCK) return 0; if (errno == 0 || errno == EINTR) continue; else { avc_log(SELINUX_ERROR, "%s: netlink recvfrom: error %d\n", avc_prefix, errno); return rc; } } (void)avc_netlink_process(buf); } return 0; } /* run routine for the netlink listening thread */ void avc_netlink_loop(void) { int rc; char buf[1024] __attribute__ ((aligned)); while (1) { errno = 0; rc = avc_netlink_receive(buf, sizeof(buf), 1); if (rc < 0) { if (errno == 0 || errno == EINTR) continue; else { avc_log(SELINUX_ERROR, "%s: netlink recvfrom: error %d\n", avc_prefix, errno); break; } } rc = avc_netlink_process(buf); if (rc < 0) break; } close(fd); fd = -1; avc_netlink_trouble = 1; avc_log(SELINUX_ERROR, "%s: netlink thread: errors encountered, terminating\n", avc_prefix); } int avc_netlink_acquire_fd(void) { avc_app_main_loop = 1; return fd; } void avc_netlink_release_fd(void) { avc_app_main_loop = 0; } libselinux/src/avc_internal.h0100644 0000000 0000000 00000011753 13756670063 015414 0ustar000000000 0000000 /* * This file describes the internal interface used by the AVC * for calling the user-supplied memory allocation, supplemental * auditing, and locking routine, as well as incrementing the * statistics fields. * * Author : Eamon Walsh */ #ifndef _SELINUX_AVC_INTERNAL_H_ #define _SELINUX_AVC_INTERNAL_H_ #include #include #include #include #include "callbacks.h" #include "dso.h" /* callback pointers */ extern void *(*avc_func_malloc) (size_t) hidden; extern void (*avc_func_free) (void *)hidden; extern void (*avc_func_log) (const char *, ...) __attribute__((__format__(printf,1,2))) hidden; extern void (*avc_func_audit) (void *, security_class_t, char *, size_t)hidden; extern int avc_using_threads hidden; extern int avc_app_main_loop hidden; extern void *(*avc_func_create_thread) (void (*)(void))hidden; extern void (*avc_func_stop_thread) (void *)hidden; extern void *(*avc_func_alloc_lock) (void)hidden; extern void (*avc_func_get_lock) (void *)hidden; extern void (*avc_func_release_lock) (void *)hidden; extern void (*avc_func_free_lock) (void *)hidden; static inline void set_callbacks(const struct avc_memory_callback *mem_cb, const struct avc_log_callback *log_cb, const struct avc_thread_callback *thread_cb, const struct avc_lock_callback *lock_cb) { if (mem_cb) { avc_func_malloc = mem_cb->func_malloc; avc_func_free = mem_cb->func_free; } if (log_cb) { avc_func_log = log_cb->func_log; avc_func_audit = log_cb->func_audit; } if (thread_cb) { avc_using_threads = 1; avc_func_create_thread = thread_cb->func_create_thread; avc_func_stop_thread = thread_cb->func_stop_thread; } if (lock_cb) { avc_func_alloc_lock = lock_cb->func_alloc_lock; avc_func_get_lock = lock_cb->func_get_lock; avc_func_release_lock = lock_cb->func_release_lock; avc_func_free_lock = lock_cb->func_free_lock; } } /* message prefix and enforcing mode*/ #define AVC_PREFIX_SIZE 16 extern char avc_prefix[AVC_PREFIX_SIZE] hidden; extern int avc_running hidden; extern int avc_enforcing hidden; extern int avc_setenforce hidden; /* user-supplied callback interface for avc */ static inline void *avc_malloc(size_t size) { return avc_func_malloc ? avc_func_malloc(size) : malloc(size); } static inline void avc_free(void *ptr) { if (avc_func_free) avc_func_free(ptr); else free(ptr); } /* this is a macro in order to use the variadic capability. */ #define avc_log(type, format...) \ if (avc_func_log) \ avc_func_log(format); \ else \ selinux_log(type, format); static inline void avc_suppl_audit(void *ptr, security_class_t class, char *buf, size_t len) { if (avc_func_audit) avc_func_audit(ptr, class, buf, len); else selinux_audit(ptr, class, buf, len); } static inline void *avc_create_thread(void (*run) (void)) { return avc_func_create_thread ? avc_func_create_thread(run) : NULL; } static inline void avc_stop_thread(void *thread) { if (avc_func_stop_thread) avc_func_stop_thread(thread); } static inline void *avc_alloc_lock(void) { return avc_func_alloc_lock ? avc_func_alloc_lock() : NULL; } static inline void avc_get_lock(void *lock) { if (avc_func_get_lock) avc_func_get_lock(lock); } static inline void avc_release_lock(void *lock) { if (avc_func_release_lock) avc_func_release_lock(lock); } static inline void avc_free_lock(void *lock) { if (avc_func_free_lock) avc_func_free_lock(lock); } /* statistics helper routines */ #ifdef AVC_CACHE_STATS #define avc_cache_stats_incr(field) \ cache_stats.field ++; #define avc_cache_stats_add(field, num) \ cache_stats.field += num; #else #define avc_cache_stats_incr(field) #define avc_cache_stats_add(field, num) #endif /* logging helper routines */ #define AVC_AUDIT_BUFSIZE 1024 /* again, we need the variadic capability here */ #define log_append(buf,format...) \ snprintf(buf+strlen(buf), AVC_AUDIT_BUFSIZE-strlen(buf), format) /* internal callbacks */ int avc_ss_grant(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno) hidden; int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, access_vector_t * out_retained) hidden; int avc_ss_revoke(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno) hidden; int avc_ss_reset(uint32_t seqno) hidden; int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, uint32_t enable) hidden; int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, uint32_t enable) hidden; /* netlink kernel message code */ extern int avc_netlink_trouble hidden; hidden_proto(avc_av_stats) hidden_proto(avc_cleanup) hidden_proto(avc_reset) hidden_proto(avc_audit) hidden_proto(avc_has_perm_noaudit) #endif /* _SELINUX_AVC_INTERNAL_H_ */ libselinux/src/avc_sidtab.c0100644 0000000 0000000 00000005516 13756670063 015041 0ustar000000000 0000000 /* * Implementation of the userspace SID hashtable. * * Author : Eamon Walsh, */ #include #include #include #include #include #include "selinux_internal.h" #include #include "avc_sidtab.h" #include "avc_internal.h" static inline unsigned sidtab_hash(const char * key) { char *p, *keyp; unsigned int size; unsigned int val; val = 0; keyp = (char *)key; size = strlen(keyp); for (p = keyp; (unsigned int)(p - keyp) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (SIDTAB_SIZE - 1); } int sidtab_init(struct sidtab *s) { int i, rc = 0; s->htable = (struct sidtab_node **)avc_malloc (sizeof(struct sidtab_node *) * SIDTAB_SIZE); if (!s->htable) { rc = -1; goto out; } for (i = 0; i < SIDTAB_SIZE; i++) s->htable[i] = NULL; s->nel = 0; out: return rc; } int sidtab_insert(struct sidtab *s, const char * ctx) { int hvalue, rc = 0; struct sidtab_node *newnode; char * newctx; newnode = (struct sidtab_node *)avc_malloc(sizeof(*newnode)); if (!newnode) { rc = -1; goto out; } newctx = (char *) strdup(ctx); if (!newctx) { rc = -1; avc_free(newnode); goto out; } hvalue = sidtab_hash(newctx); newnode->next = s->htable[hvalue]; newnode->sid_s.ctx = newctx; newnode->sid_s.refcnt = 1; /* unused */ s->htable[hvalue] = newnode; s->nel++; out: return rc; } int sidtab_context_to_sid(struct sidtab *s, const char * ctx, security_id_t * sid) { int hvalue, rc = 0; struct sidtab_node *cur; *sid = NULL; hvalue = sidtab_hash(ctx); loop: cur = s->htable[hvalue]; while (cur != NULL && strcmp(cur->sid_s.ctx, ctx)) cur = cur->next; if (cur == NULL) { /* need to make a new entry */ rc = sidtab_insert(s, ctx); if (rc) goto out; goto loop; /* find the newly inserted node */ } *sid = &cur->sid_s; out: return rc; } void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen) { int i, chain_len, slots_used, max_chain_len; struct sidtab_node *cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < SIDTAB_SIZE; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } snprintf(buf, buflen, "%s: %u SID entries and %d/%d buckets used, longest " "chain length %d\n", avc_prefix, h->nel, slots_used, SIDTAB_SIZE, max_chain_len); } void sidtab_destroy(struct sidtab *s) { int i; struct sidtab_node *cur, *temp; if (!s) return; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; freecon(temp->sid_s.ctx); avc_free(temp); } s->htable[i] = NULL; } avc_free(s->htable); s->htable = NULL; } libselinux/src/avc_sidtab.h0100644 0000000 0000000 00000001636 13756670063 015045 0ustar000000000 0000000 /* * A security identifier table (sidtab) is a hash table * of security context structures indexed by SID value. */ #ifndef _SELINUX_AVC_SIDTAB_H_ #define _SELINUX_AVC_SIDTAB_H_ #include #include #include "dso.h" struct sidtab_node { struct security_id sid_s; struct sidtab_node *next; }; #define SIDTAB_HASH_BITS 7 #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) #define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS struct sidtab { struct sidtab_node **htable; unsigned nel; }; int sidtab_init(struct sidtab *s) hidden; int sidtab_insert(struct sidtab *s, const char * ctx) hidden; int sidtab_context_to_sid(struct sidtab *s, const char * ctx, security_id_t * sid) hidden; void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) hidden; void sidtab_destroy(struct sidtab *s) hidden; #endif /* _SELINUX_AVC_SIDTAB_H_ */ libselinux/src/booleans.c0100644 0000000 0000000 00000026443 13756670063 014546 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Modified: * Dan Walsh - Added security_load_booleans(). */ #ifndef DISABLE_BOOL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #define SELINUX_BOOL_DIR "/booleans/" static int filename_select(const struct dirent *d) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) return 0; return 1; } int security_get_boolean_names(char ***names, int *len) { char path[PATH_MAX]; int i, rc; struct dirent **namelist; char **n; if (!len || names == NULL) { errno = EINVAL; return -1; } if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR); *len = scandir(path, &namelist, &filename_select, alphasort); if (*len <= 0) { errno = ENOENT; return -1; } n = (char **)malloc(sizeof(char *) * *len); if (!n) { rc = -1; goto bad; } for (i = 0; i < *len; i++) { n[i] = strdup(namelist[i]->d_name); if (!n[i]) { rc = -1; goto bad_freen; } } rc = 0; *names = n; out: for (i = 0; i < *len; i++) { free(namelist[i]); } free(namelist); return rc; bad_freen: for (--i; i >= 0; --i) free(n[i]); free(n); bad: goto out; } char *selinux_boolean_sub(const char *name) { char *sub = NULL; char *line_buf = NULL; size_t line_len; FILE *cfg; if (!name) return NULL; cfg = fopen(selinux_booleans_subs_path(), "re"); if (!cfg) goto out; while (getline(&line_buf, &line_len, cfg) != -1) { char *ptr; char *src = line_buf; char *dst; while (*src && isspace(*src)) src++; if (!*src) continue; if (src[0] == '#') continue; ptr = src; while (*ptr && !isspace(*ptr)) ptr++; *ptr++ = '\0'; if (strcmp(src, name) != 0) continue; dst = ptr; while (*dst && isspace(*dst)) dst++; if (!*dst) continue; ptr=dst; while (*ptr && !isspace(*ptr)) ptr++; *ptr='\0'; sub = strdup(dst); break; } free(line_buf); fclose(cfg); out: if (!sub) sub = strdup(name); return sub; } static int bool_open(const char *name, int flag) { char *fname = NULL; char *alt_name = NULL; int len; int fd = -1; int ret; char *ptr; if (!name) { errno = EINVAL; return -1; } /* note the 'sizeof' gets us enough room for the '\0' */ len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); fname = malloc(sizeof(char) * len); if (!fname) return -1; ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); if (ret < 0) goto out; assert(ret < len); fd = open(fname, flag); if (fd >= 0 || errno != ENOENT) goto out; alt_name = selinux_boolean_sub(name); if (!alt_name) goto out; /* note the 'sizeof' gets us enough room for the '\0' */ len = strlen(alt_name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); ptr = realloc(fname, len); if (!ptr) goto out; fname = ptr; ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); if (ret < 0) goto out; assert(ret < len); fd = open(fname, flag); out: free(fname); free(alt_name); return fd; } #define STRBUF_SIZE 3 static int get_bool_value(const char *name, char **buf) { int fd, len; int errno_tmp; if (!selinux_mnt) { errno = ENOENT; return -1; } *buf = malloc(sizeof(char) * (STRBUF_SIZE + 1)); if (!*buf) return -1; (*buf)[STRBUF_SIZE] = 0; fd = bool_open(name, O_RDONLY | O_CLOEXEC); if (fd < 0) goto out_err; len = read(fd, *buf, STRBUF_SIZE); errno_tmp = errno; close(fd); errno = errno_tmp; if (len != STRBUF_SIZE) goto out_err; return 0; out_err: free(*buf); return -1; } int security_get_boolean_pending(const char *name) { char *buf; int val; if (get_bool_value(name, &buf)) return -1; if (atoi(&buf[1])) val = 1; else val = 0; free(buf); return val; } int security_get_boolean_active(const char *name) { char *buf; int val; if (get_bool_value(name, &buf)) return -1; buf[1] = '\0'; if (atoi(buf)) val = 1; else val = 0; free(buf); return val; } int security_set_boolean(const char *name, int value) { int fd, ret; char buf[2]; if (!selinux_mnt) { errno = ENOENT; return -1; } if (value < 0 || value > 1) { errno = EINVAL; return -1; } fd = bool_open(name, O_WRONLY | O_CLOEXEC); if (fd < 0) return -1; if (value) buf[0] = '1'; else buf[0] = '0'; buf[1] = '\0'; ret = write(fd, buf, 2); close(fd); if (ret > 0) return 0; else return -1; } int security_commit_booleans(void) { int fd, ret; char buf[2]; char path[PATH_MAX]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt); fd = open(path, O_WRONLY | O_CLOEXEC); if (fd < 0) return -1; buf[0] = '1'; buf[1] = '\0'; ret = write(fd, buf, 2); close(fd); if (ret > 0) return 0; else return -1; } static char *strtrim(char *dest, char *source, int size) { int i = 0; char *ptr = source; i = 0; while (isspace(*ptr) && i < size) { ptr++; i++; } strncpy(dest, ptr, size); for (i = strlen(dest) - 1; i > 0; i--) { if (!isspace(dest[i])) break; } dest[i + 1] = '\0'; return dest; } static int process_boolean(char *buffer, char *name, int namesize, int *val) { char name1[BUFSIZ]; char *ptr = NULL; char *tok; /* Skip spaces */ while (isspace(buffer[0])) buffer++; /* Ignore comments */ if (buffer[0] == '#') return 0; tok = strtok_r(buffer, "=", &ptr); if (!tok) { errno = EINVAL; return -1; } strncpy(name1, tok, BUFSIZ - 1); strtrim(name, name1, namesize - 1); tok = strtok_r(NULL, "\0", &ptr); if (!tok) { errno = EINVAL; return -1; } while (isspace(*tok)) tok++; *val = -1; if (isdigit(tok[0])) *val = atoi(tok); else if (!strncasecmp(tok, "true", sizeof("true") - 1)) *val = 1; else if (!strncasecmp(tok, "false", sizeof("false") - 1)) *val = 0; if (*val != 0 && *val != 1) { errno = EINVAL; return -1; } return 1; } static int save_booleans(size_t boolcnt, SELboolean * boollist) { ssize_t len; size_t i; char outbuf[BUFSIZ]; char *inbuf = NULL; /* Open file */ const char *bool_file = selinux_booleans_path(); char local_bool_file[PATH_MAX]; char tmp_bool_file[PATH_MAX]; FILE *boolf; int fd; int *used = (int *)malloc(sizeof(int) * boolcnt); if (!used) { return -1; } /* zero out used field */ for (i = 0; i < boolcnt; i++) used[i] = 0; snprintf(tmp_bool_file, sizeof(tmp_bool_file), "%s.XXXXXX", bool_file); fd = mkstemp(tmp_bool_file); if (fd < 0) { free(used); return -1; } snprintf(local_bool_file, sizeof(local_bool_file), "%s.local", bool_file); boolf = fopen(local_bool_file, "re"); if (boolf != NULL) { ssize_t ret; size_t size = 0; int val; char boolname[BUFSIZ-3]; char *buffer; inbuf = NULL; __fsetlocking(boolf, FSETLOCKING_BYCALLER); while ((len = getline(&inbuf, &size, boolf)) > 0) { buffer = strdup(inbuf); if (!buffer) goto close_remove_fail; ret = process_boolean(inbuf, boolname, sizeof(boolname), &val); if (ret != 1) { ret = write(fd, buffer, len); free(buffer); if (ret != len) goto close_remove_fail; } else { free(buffer); for (i = 0; i < boolcnt; i++) { if (strcmp(boollist[i].name, boolname) == 0) { snprintf(outbuf, sizeof(outbuf), "%s=%d\n", boolname, boollist[i].value); len = strlen(outbuf); used[i] = 1; if (write(fd, outbuf, len) != len) goto close_remove_fail; else break; } } if (i == boolcnt) { val = !!val; snprintf(outbuf, sizeof(outbuf), "%s=%d\n", boolname, val); len = strlen(outbuf); if (write(fd, outbuf, len) != len) goto close_remove_fail; } } free(inbuf); inbuf = NULL; } fclose(boolf); } for (i = 0; i < boolcnt; i++) { if (used[i] == 0) { snprintf(outbuf, sizeof(outbuf), "%s=%d\n", boollist[i].name, boollist[i].value); len = strlen(outbuf); if (write(fd, outbuf, len) != len) { close_remove_fail: free(inbuf); close(fd); remove_fail: unlink(tmp_bool_file); free(used); return -1; } } } if (fchmod(fd, S_IRUSR | S_IWUSR) != 0) goto close_remove_fail; close(fd); if (rename(tmp_bool_file, local_bool_file) != 0) goto remove_fail; free(used); return 0; } static void rollback(SELboolean * boollist, int end) { int i; for (i = 0; i < end; i++) security_set_boolean(boollist[i].name, security_get_boolean_active(boollist[i]. name)); } int security_set_boolean_list(size_t boolcnt, SELboolean * boollist, int permanent) { size_t i; for (i = 0; i < boolcnt; i++) { boollist[i].value = !!boollist[i].value; if (security_set_boolean(boollist[i].name, boollist[i].value)) { rollback(boollist, i); return -1; } } /* OK, let's do the commit */ if (security_commit_booleans()) { return -1; } if (permanent) return save_booleans(boolcnt, boollist); return 0; } int security_load_booleans(char *path) { FILE *boolf; char *inbuf; char localbools[BUFSIZ]; size_t len = 0, errors = 0; int val; char name[BUFSIZ]; boolf = fopen(path ? path : selinux_booleans_path(), "re"); if (boolf == NULL) goto localbool; __fsetlocking(boolf, FSETLOCKING_BYCALLER); while (getline(&inbuf, &len, boolf) > 0) { int ret = process_boolean(inbuf, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) if (security_set_boolean(name, val) < 0) { errors++; } } fclose(boolf); localbool: snprintf(localbools, sizeof(localbools), "%s.local", (path ? path : selinux_booleans_path())); boolf = fopen(localbools, "re"); if (boolf != NULL) { int ret; __fsetlocking(boolf, FSETLOCKING_BYCALLER); while (getline(&inbuf, &len, boolf) > 0) { ret = process_boolean(inbuf, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) if (security_set_boolean(name, val) < 0) { errors++; } } fclose(boolf); } if (security_commit_booleans() < 0) return -1; if (errors) errno = EINVAL; return errors ? -1 : 0; } #else #include #include "selinux_internal.h" int security_set_boolean_list(size_t boolcnt __attribute__((unused)), SELboolean * boollist __attribute__((unused)), int permanent __attribute__((unused))) { return -1; } int security_load_booleans(char *path __attribute__((unused))) { return -1; } int security_get_boolean_names(char ***names __attribute__((unused)), int *len __attribute__((unused))) { return -1; } int security_get_boolean_pending(const char *name __attribute__((unused))) { return -1; } int security_get_boolean_active(const char *name __attribute__((unused))) { return -1; } int security_set_boolean(const char *name __attribute__((unused)), int value __attribute__((unused))) { return -1; } int security_commit_booleans(void) { return -1; } char *selinux_boolean_sub(const char *name __attribute__((unused))) { return NULL; } #endif hidden_def(security_get_boolean_names) hidden_def(selinux_boolean_sub) hidden_def(security_get_boolean_active) hidden_def(security_set_boolean) hidden_def(security_commit_booleans) libselinux/src/callbacks.c0100644 0000000 0000000 00000005034 13756670063 014654 0ustar000000000 0000000 /* * User-supplied callbacks and default implementations. * Class and permission mappings. */ #include #include #include #include #include #include "callbacks.h" /* default implementations */ static int __attribute__ ((format(printf, 2, 3))) default_selinux_log(int type __attribute__((unused)), const char *fmt, ...) { int rc; va_list ap; va_start(ap, fmt); rc = vfprintf(stderr, fmt, ap); va_end(ap); return rc; } static int default_selinux_audit(void *ptr __attribute__((unused)), security_class_t cls __attribute__((unused)), char *buf __attribute__((unused)), size_t len __attribute__((unused))) { return 0; } static int default_selinux_validate(char **ctx) { #ifndef BUILD_HOST return security_check_context(*ctx); #else (void) ctx; return 0; #endif } static int default_selinux_setenforce(int enforcing __attribute__((unused))) { return 0; } static int default_selinux_policyload(int seqno __attribute__((unused))) { return 0; } /* callback pointers */ int __attribute__ ((format(printf, 2, 3))) (*selinux_log)(int, const char *, ...) = default_selinux_log; int (*selinux_audit) (void *, security_class_t, char *, size_t) = default_selinux_audit; int (*selinux_validate)(char **ctx) = default_selinux_validate; int (*selinux_netlink_setenforce) (int enforcing) = default_selinux_setenforce; int (*selinux_netlink_policyload) (int seqno) = default_selinux_policyload; /* callback setting function */ void selinux_set_callback(int type, union selinux_callback cb) { switch (type) { case SELINUX_CB_LOG: selinux_log = cb.func_log; break; case SELINUX_CB_AUDIT: selinux_audit = cb.func_audit; break; case SELINUX_CB_VALIDATE: selinux_validate = cb.func_validate; break; case SELINUX_CB_SETENFORCE: selinux_netlink_setenforce = cb.func_setenforce; break; case SELINUX_CB_POLICYLOAD: selinux_netlink_policyload = cb.func_policyload; break; } } /* callback getting function */ union selinux_callback selinux_get_callback(int type) { union selinux_callback cb; switch (type) { case SELINUX_CB_LOG: cb.func_log = selinux_log; break; case SELINUX_CB_AUDIT: cb.func_audit = selinux_audit; break; case SELINUX_CB_VALIDATE: cb.func_validate = selinux_validate; break; case SELINUX_CB_SETENFORCE: cb.func_setenforce = selinux_netlink_setenforce; break; case SELINUX_CB_POLICYLOAD: cb.func_policyload = selinux_netlink_policyload; break; default: memset(&cb, 0, sizeof(cb)); errno = EINVAL; break; } return cb; } libselinux/src/callbacks.h0100644 0000000 0000000 00000001356 13756670063 014664 0ustar000000000 0000000 /* * This file describes the callbacks passed to selinux_init() and available * for use from the library code. They all have default implementations. */ #ifndef _SELINUX_CALLBACKS_H_ #define _SELINUX_CALLBACKS_H_ #include #include #include #include #include "dso.h" /* callback pointers */ extern int __attribute__ ((format(printf, 2, 3))) (*selinux_log) (int type, const char *, ...) hidden; extern int (*selinux_audit) (void *, security_class_t, char *, size_t) hidden; extern int (*selinux_validate)(char **ctx) hidden; extern int (*selinux_netlink_setenforce) (int enforcing) hidden; extern int (*selinux_netlink_policyload) (int seqno) hidden; #endif /* _SELINUX_CALLBACKS_H_ */ libselinux/src/canonicalize_context.c0100644 0000000 0000000 00000003030 13756670063 017132 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include int security_canonicalize_context_raw(const char * con, char ** canoncon) { char path[PATH_MAX]; char *buf; size_t size; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/context", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } strncpy(buf, con, size); ret = write(fd, buf, strlen(buf) + 1); if (ret < 0) goto out2; memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0 && errno == EINVAL) { /* Fall back to the original context for kernels that do not support the extended interface. */ strncpy(buf, con, size); } *canoncon = strdup(buf); if (!(*canoncon)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_canonicalize_context_raw) int security_canonicalize_context(const char * con, char ** canoncon) { int ret; char * rcon; char * rcanoncon; if (selinux_trans_to_raw_context(con, &rcon)) return -1; ret = security_canonicalize_context_raw(rcon, &rcanoncon); freecon(rcon); if (!ret) { ret = selinux_raw_to_trans_context(rcanoncon, canoncon); freecon(rcanoncon); } return ret; } hidden_def(security_canonicalize_context) libselinux/src/checkAccess.c0100644 0000000 0000000 00000005454 13756670063 015142 0ustar000000000 0000000 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ #include #include #include #include #include "selinux_internal.h" #include #include "avc_internal.h" static pthread_once_t once = PTHREAD_ONCE_INIT; static int selinux_enabled; static int avc_reset_callback(uint32_t event __attribute__((unused)), security_id_t ssid __attribute__((unused)), security_id_t tsid __attribute__((unused)), security_class_t tclass __attribute__((unused)), access_vector_t perms __attribute__((unused)), access_vector_t *out_retained __attribute__((unused))) { flush_class_cache(); return 0; } static void avc_init_once(void) { selinux_enabled = is_selinux_enabled(); if (selinux_enabled == 1) { if (avc_open(NULL, 0)) return; avc_add_callback(avc_reset_callback, AVC_CALLBACK_RESET, 0, 0, 0, 0); } } int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) { int rc; security_id_t scon_id; security_id_t tcon_id; security_class_t sclass; access_vector_t av; __selinux_once(once, avc_init_once); if (selinux_enabled != 1) return 0; rc = avc_context_to_sid(scon, &scon_id); if (rc < 0) return rc; rc = avc_context_to_sid(tcon, &tcon_id); if (rc < 0) return rc; (void) avc_netlink_check_nb(); sclass = string_to_security_class(class); if (sclass == 0) { rc = errno; avc_log(SELINUX_ERROR, "Unknown class %s", class); if (security_deny_unknown() == 0) return 0; errno = rc; return -1; } av = string_to_av_perm(sclass, perm); if (av == 0) { rc = errno; avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class); if (security_deny_unknown() == 0) return 0; errno = rc; return -1; } return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux); } int selinux_check_passwd_access(access_vector_t requested) { int status = -1; char *user_context; if (is_selinux_enabled() == 0) return 0; if (getprevcon_raw(&user_context) == 0) { security_class_t passwd_class; struct av_decision avd; int retval; passwd_class = string_to_security_class("passwd"); if (passwd_class == 0) { freecon(user_context); return 0; } retval = security_compute_av_raw(user_context, user_context, passwd_class, requested, &avd); if ((retval == 0) && ((requested & avd.allowed) == requested)) { status = 0; } freecon(user_context); } if (status != 0 && security_getenforce() == 0) status = 0; return status; } hidden_def(selinux_check_passwd_access) int checkPasswdAccess(access_vector_t requested) { return selinux_check_passwd_access(requested); } libselinux/src/check_context.c0100644 0000000 0000000 00000001525 13756670063 015557 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include int security_check_context_raw(const char * con) { char path[PATH_MAX]; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/context", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; ret = write(fd, con, strlen(con) + 1); close(fd); if (ret < 0) return -1; return 0; } hidden_def(security_check_context_raw) int security_check_context(const char * con) { int ret; char * rcon; if (selinux_trans_to_raw_context(con, &rcon)) return -1; ret = security_check_context_raw(rcon); freecon(rcon); return ret; } hidden_def(security_check_context) libselinux/src/checkreqprot.c0100644 0000000 0000000 00000001340 13756670063 015423 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_get_checkreqprot(void) { int fd, ret, checkreqprot = 0; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof(path), "%s/checkreqprot", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; memset(buf, 0, sizeof(buf)); ret = read(fd, buf, sizeof(buf) - 1); close(fd); if (ret < 0) return -1; if (sscanf(buf, "%d", &checkreqprot) != 1) return -1; return checkreqprot; } hidden_def(security_get_checkreqprot); libselinux/src/compute_av.c0100644 0000000 0000000 00000006701 13756670063 015101 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" int security_compute_av_flags_raw(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd) { char path[PATH_MAX]; char *buf; size_t len; int fd, ret; security_class_t kclass; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/access", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; len = selinux_page_size; buf = malloc(len); if (!buf) { ret = -1; goto out; } kclass = unmap_class(tclass); snprintf(buf, len, "%s %s %hu %x", scon, tcon, kclass, unmap_perm(tclass, requested)); ret = write(fd, buf, strlen(buf)); if (ret < 0) goto out2; memset(buf, 0, len); ret = read(fd, buf, len - 1); if (ret < 0) goto out2; ret = sscanf(buf, "%x %x %x %x %u %x", &avd->allowed, &avd->decided, &avd->auditallow, &avd->auditdeny, &avd->seqno, &avd->flags); if (ret < 5) { ret = -1; goto out2; } else if (ret < 6) avd->flags = 0; /* * If the tclass could not be mapped to a kernel class at all, the * kernel will have already set avd according to the * handle_unknown flag and we do not need to do anything further. * Otherwise, we must map the permissions within the returned * avd to the userspace permission values. */ if (kclass != 0) map_decision(tclass, avd); ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_compute_av_flags_raw) int security_compute_av_raw(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd) { struct av_decision lavd; int ret; ret = security_compute_av_flags_raw(scon, tcon, tclass, requested, &lavd); if (ret == 0) { avd->allowed = lavd.allowed; avd->decided = lavd.decided; avd->auditallow = lavd.auditallow; avd->auditdeny = lavd.auditdeny; avd->seqno = lavd.seqno; /* NOTE: * We should not return avd->flags via the interface * due to the binary compatibility. */ } return ret; } hidden_def(security_compute_av_raw) int security_compute_av_flags(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd) { char * rscon; char * rtcon; int ret; if (selinux_trans_to_raw_context(scon, &rscon)) return -1; if (selinux_trans_to_raw_context(tcon, &rtcon)) { freecon(rscon); return -1; } ret = security_compute_av_flags_raw(rscon, rtcon, tclass, requested, avd); freecon(rscon); freecon(rtcon); return ret; } hidden_def(security_compute_av_flags) int security_compute_av(const char * scon, const char * tcon, security_class_t tclass, access_vector_t requested, struct av_decision *avd) { struct av_decision lavd; int ret; ret = security_compute_av_flags(scon, tcon, tclass, requested, &lavd); if (ret == 0) { avd->allowed = lavd.allowed; avd->decided = lavd.decided; avd->auditallow = lavd.auditallow; avd->auditdeny = lavd.auditdeny; avd->seqno = lavd.seqno; /* NOTE: * We should not return avd->flags via the interface * due to the binary compatibility. */ } return ret; } hidden_def(security_compute_av) libselinux/src/compute_create.c0100644 0000000 0000000 00000006212 13756670063 015733 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" static int object_name_encode(const char *objname, char *buffer, size_t buflen) { int code; size_t offset = 0; if (buflen - offset < 1) return -1; buffer[offset++] = ' '; do { code = *objname++; if (isalnum(code) || code == '\0' || code == '-' || code == '.' || code == '_' || code == '~') { if (buflen - offset < 1) return -1; buffer[offset++] = code; } else if (code == ' ') { if (buflen - offset < 1) return -1; buffer[offset++] = '+'; } else { static const char *table = "0123456789ABCDEF"; int l = (code & 0x0f); int h = (code & 0xf0) >> 4; if (buflen - offset < 3) return -1; buffer[offset++] = '%'; buffer[offset++] = table[h]; buffer[offset++] = table[l]; } } while (code != '\0'); return 0; } int security_compute_create_name_raw(const char * scon, const char * tcon, security_class_t tclass, const char *objname, char ** newcon) { char path[PATH_MAX]; char *buf; size_t size; int fd, ret, len; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/create", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } len = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); if (objname && object_name_encode(objname, buf + len, size - len) < 0) { errno = ENAMETOOLONG; ret = -1; goto out2; } ret = write(fd, buf, strlen(buf)); if (ret < 0) goto out2; memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0) goto out2; *newcon = strdup(buf); if (!(*newcon)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_compute_create_name_raw) int security_compute_create_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { return security_compute_create_name_raw(scon, tcon, tclass, NULL, newcon); } hidden_def(security_compute_create_raw) int security_compute_create_name(const char * scon, const char * tcon, security_class_t tclass, const char *objname, char ** newcon) { int ret; char * rscon; char * rtcon; char * rnewcon; if (selinux_trans_to_raw_context(scon, &rscon)) return -1; if (selinux_trans_to_raw_context(tcon, &rtcon)) { freecon(rscon); return -1; } ret = security_compute_create_name_raw(rscon, rtcon, tclass, objname, &rnewcon); freecon(rscon); freecon(rtcon); if (!ret) { ret = selinux_raw_to_trans_context(rnewcon, newcon); freecon(rnewcon); } return ret; } hidden_def(security_compute_create_name) int security_compute_create(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { return security_compute_create_name(scon, tcon, tclass, NULL, newcon); } hidden_def(security_compute_create) libselinux/src/compute_member.c0100644 0000000 0000000 00000003204 13756670063 015735 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" int security_compute_member_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { char path[PATH_MAX]; char *buf; size_t size; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/member", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ret = write(fd, buf, strlen(buf)); if (ret < 0) goto out2; memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0) goto out2; *newcon = strdup(buf); if (!(*newcon)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_compute_member_raw) int security_compute_member(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { int ret; char * rscon; char * rtcon; char * rnewcon; if (selinux_trans_to_raw_context(scon, &rscon)) return -1; if (selinux_trans_to_raw_context(tcon, &rtcon)) { freecon(rscon); return -1; } ret = security_compute_member_raw(rscon, rtcon, tclass, &rnewcon); freecon(rscon); freecon(rtcon); if (!ret) { if (selinux_raw_to_trans_context(rnewcon, newcon)) { *newcon = NULL; ret = -1; } freecon(rnewcon); } return ret; } libselinux/src/compute_relabel.c0100644 0000000 0000000 00000003151 13756670063 016075 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" int security_compute_relabel_raw(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { char path[PATH_MAX]; char *buf; size_t size; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/relabel", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ret = write(fd, buf, strlen(buf)); if (ret < 0) goto out2; memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0) goto out2; *newcon = strdup(buf); if (!*newcon) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_compute_relabel_raw) int security_compute_relabel(const char * scon, const char * tcon, security_class_t tclass, char ** newcon) { int ret; char * rscon; char * rtcon; char * rnewcon; if (selinux_trans_to_raw_context(scon, &rscon)) return -1; if (selinux_trans_to_raw_context(tcon, &rtcon)) { freecon(rscon); return -1; } ret = security_compute_relabel_raw(rscon, rtcon, tclass, &rnewcon); freecon(rscon); freecon(rtcon); if (!ret) { ret = selinux_raw_to_trans_context(rnewcon, newcon); freecon(rnewcon); } return ret; } libselinux/src/compute_user.c0100644 0000000 0000000 00000003477 13756670063 015460 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include int security_compute_user_raw(const char * scon, const char *user, char *** con) { char path[PATH_MAX]; char **ary; char *buf, *ptr; size_t size; int fd, ret; unsigned int i, nel; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/user", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } snprintf(buf, size, "%s %s", scon, user); ret = write(fd, buf, strlen(buf)); if (ret < 0) goto out2; memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0) goto out2; if (sscanf(buf, "%u", &nel) != 1) { ret = -1; goto out2; } ary = malloc((nel + 1) * sizeof(char *)); if (!ary) { ret = -1; goto out2; } ptr = buf + strlen(buf) + 1; for (i = 0; i < nel; i++) { ary[i] = strdup(ptr); if (!ary[i]) { freeconary(ary); ret = -1; goto out2; } ptr += strlen(ptr) + 1; } ary[nel] = NULL; *con = ary; ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_compute_user_raw) int security_compute_user(const char * scon, const char *user, char *** con) { int ret; char * rscon; if (selinux_trans_to_raw_context(scon, &rscon)) return -1; ret = security_compute_user_raw(rscon, user, con); freecon(rscon); if (!ret) { char **ptr, *tmpcon; for (ptr = *con; *ptr; ptr++) { if (selinux_raw_to_trans_context(*ptr, &tmpcon)) { freeconary(*con); *con = NULL; return -1; } freecon(*ptr); *ptr = tmpcon; } } return ret; } hidden_def(security_compute_user) libselinux/src/context.c0100644 0000000 0000000 00000007757 13756670063 014437 0ustar000000000 0000000 #include "context_internal.h" #include #include #include #include #define COMP_USER 0 #define COMP_ROLE 1 #define COMP_TYPE 2 #define COMP_RANGE 3 typedef struct { char *current_str; /* This is made up-to-date only when needed */ char *(component[4]); } context_private_t; /* * Allocate a new context, initialized from str. There must be 3 or * 4 colon-separated components and no whitespace in any component other * than the MLS component. */ context_t context_new(const char *str) { int i, count; errno = 0; context_private_t *n = (context_private_t *) malloc(sizeof(context_private_t)); context_t result = (context_t) malloc(sizeof(context_s_t)); const char *p, *tok; if (result) result->ptr = n; else free(n); if (n == 0 || result == 0) { goto err; } n->current_str = n->component[0] = n->component[1] = n->component[2] = n->component[3] = 0; for (i = count = 0, p = str; *p; p++) { switch (*p) { case ':': count++; break; case '\n': case '\t': case '\r': goto err; /* sanity check */ case ' ': if (count < 3) goto err; /* sanity check */ } } /* * Could be anywhere from 2 - 5 * e.g user:role:type to user:role:type:sens1:cata-sens2:catb */ if (count < 2 || count > 5) { /* might not have a range */ goto err; } n->component[3] = 0; for (i = 0, tok = str; *tok; i++) { if (i < 3) for (p = tok; *p && *p != ':'; p++) { /* empty */ } else { /* MLS range is one component */ for (p = tok; *p; p++) { /* empty */ } } n->component[i] = (char *)malloc(p - tok + 1); if (n->component[i] == 0) goto err; strncpy(n->component[i], tok, p - tok); n->component[i][p - tok] = '\0'; tok = *p ? p + 1 : p; } return result; err: if (errno == 0) errno = EINVAL; context_free(result); return 0; } hidden_def(context_new) static void conditional_free(char **v) { if (*v) { free(*v); } *v = 0; } /* * free all storage used by a context. Safe to call with * null pointer. */ void context_free(context_t context) { context_private_t *n; int i; if (context) { n = context->ptr; if (n) { conditional_free(&n->current_str); for (i = 0; i < 4; i++) { conditional_free(&n->component[i]); } free(n); } free(context); } } hidden_def(context_free) /* * Return a pointer to the string value of the context. */ char *context_str(context_t context) { context_private_t *n = context->ptr; int i; size_t total = 0; conditional_free(&n->current_str); for (i = 0; i < 4; i++) { if (n->component[i]) { total += strlen(n->component[i]) + 1; } } n->current_str = malloc(total); if (n->current_str != 0) { char *cp = n->current_str; cp = stpcpy(cp, n->component[0]); for (i = 1; i < 4; i++) { if (n->component[i]) { *cp++ = ':'; cp = stpcpy(cp, n->component[i]); } } } return n->current_str; } hidden_def(context_str) /* Returns nonzero iff failed */ static int set_comp(context_private_t * n, int idx, const char *str) { char *t = NULL; const char *p; if (str) { t = (char *)malloc(strlen(str) + 1); if (!t) { return 1; } for (p = str; *p; p++) { if (*p == '\t' || *p == '\n' || *p == '\r' || ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) { free(t); errno = EINVAL; return 1; } } strcpy(t, str); } conditional_free(&n->component[idx]); n->component[idx] = t; return 0; } #define def_get(name,tag) \ const char * context_ ## name ## _get(context_t context) \ { \ context_private_t *n = context->ptr; \ return n->component[tag]; \ } \ hidden_def(context_ ## name ## _get) def_get(type, COMP_TYPE) def_get(user, COMP_USER) def_get(range, COMP_RANGE) def_get(role, COMP_ROLE) #define def_set(name,tag) \ int context_ ## name ## _set(context_t context, const char* str) \ { \ return set_comp(context->ptr,tag,str);\ } \ hidden_def(context_ ## name ## _set) def_set(type, COMP_TYPE) def_set(role, COMP_ROLE) def_set(user, COMP_USER) def_set(range, COMP_RANGE) libselinux/src/context_internal.h0100644 0000000 0000000 00000000640 13756670063 016320 0ustar000000000 0000000 #include #include "dso.h" hidden_proto(context_new) hidden_proto(context_free) hidden_proto(context_str) hidden_proto(context_type_set) hidden_proto(context_type_get) hidden_proto(context_role_set) hidden_proto(context_role_get) hidden_proto(context_user_set) hidden_proto(context_user_get) hidden_proto(context_range_set) hidden_proto(context_range_get) libselinux/src/deny_unknown.c0100644 0000000 0000000 00000001330 13756670063 015446 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_deny_unknown(void) { int fd, ret, deny_unknown = 0; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof(path), "%s/deny_unknown", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; memset(buf, 0, sizeof(buf)); ret = read(fd, buf, sizeof(buf) - 1); close(fd); if (ret < 0) return -1; if (sscanf(buf, "%d", &deny_unknown) != 1) return -1; return deny_unknown; } hidden_def(security_deny_unknown); libselinux/src/disable.c0100644 0000000 0000000 00000001156 13756670063 014341 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_disable(void) { int fd, ret; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/disable", selinux_mnt); fd = open(path, O_WRONLY | O_CLOEXEC); if (fd < 0) return -1; buf[0] = '1'; buf[1] = '\0'; ret = write(fd, buf, strlen(buf)); close(fd); if (ret < 0) return -1; return 0; } hidden_def(security_disable) libselinux/src/dso.h0100644 0000000 0000000 00000001210 13756670063 013517 0ustar000000000 0000000 #ifndef _SELINUX_DSO_H #define _SELINUX_DSO_H 1 #ifdef SHARED # define hidden __attribute__ ((visibility ("hidden"))) # define hidden_proto(fct) __hidden_proto (fct, fct##_internal) # define __hidden_proto(fct, internal) \ extern __typeof (fct) internal; \ extern __typeof (fct) fct __asm (#internal) hidden; # if defined(__alpha__) || defined(__mips__) # define hidden_def(fct) \ asm (".globl " #fct "\n" #fct " = " #fct "_internal"); # else # define hidden_def(fct) \ asm (".globl " #fct "\n.set " #fct ", " #fct "_internal"); #endif #else # define hidden # define hidden_proto(fct) # define hidden_def(fct) #endif #endif libselinux/src/enabled.c0100644 0000000 0000000 00000002127 13756670063 014327 0ustar000000000 0000000 #include #include #include #include "selinux_internal.h" #include #include #include #include #include "policy.h" int is_selinux_enabled(void) { /* init_selinuxmnt() gets called before this function. We * will assume that if a selinux file system is mounted, then * selinux is enabled. */ #ifdef ANDROID return (selinux_mnt ? 1 : 0); #else return (selinux_mnt && has_selinux_config); #endif } hidden_def(is_selinux_enabled) /* * Function: is_selinux_mls_enabled() * Return: 1 on success * 0 on failure */ int is_selinux_mls_enabled(void) { char buf[20], path[PATH_MAX]; int fd, ret, enabled = 0; if (!selinux_mnt) return enabled; snprintf(path, sizeof path, "%s/mls", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return enabled; memset(buf, 0, sizeof buf); do { ret = read(fd, buf, sizeof buf - 1); } while (ret < 0 && errno == EINTR); close(fd); if (ret < 0) return enabled; if (!strcmp(buf, "1")) enabled = 1; return enabled; } hidden_def(is_selinux_mls_enabled) libselinux/src/exception.sh0100755 0000000 0000000 00000001053 13756670063 015123 0ustar000000000 0000000 function except() { case $1 in selinux_file_context_cmp) # ignore ;; *) echo " %exception $1 { \$action if (result < 0) { PyErr_SetFromErrno(PyExc_OSError); SWIG_fail; } } " ;; esac } if ! ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h then # clang does not support -aux-info so fall back to gcc gcc -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h fi for i in `awk '/.*extern int/ { print $6 }' temp.aux`; do except $i ; done rm -f -- temp.aux -.o libselinux/src/fgetfilecon.c0100644 0000000 0000000 00000002326 13756670063 015223 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" int fgetfilecon_raw(int fd, char ** context) { char *buf; ssize_t size; ssize_t ret; size = INITCONTEXTLEN + 1; buf = malloc(size); if (!buf) return -1; memset(buf, 0, size); ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); if (ret < 0 && errno == ERANGE) { char *newbuf; size = fgetxattr(fd, XATTR_NAME_SELINUX, NULL, 0); if (size < 0) goto out; size++; newbuf = realloc(buf, size); if (!newbuf) goto out; buf = newbuf; memset(buf, 0, size); ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); } out: if (ret == 0) { /* Re-map empty attribute values to errors. */ errno = ENOTSUP; ret = -1; } if (ret < 0) free(buf); else *context = buf; return ret; } hidden_def(fgetfilecon_raw) int fgetfilecon(int fd, char ** context) { char * rcontext = NULL; int ret; *context = NULL; ret = fgetfilecon_raw(fd, &rcontext); if (ret > 0) { ret = selinux_raw_to_trans_context(rcontext, context); freecon(rcontext); } if (ret >= 0 && *context) return strlen(*context) + 1; return ret; } libselinux/src/file_path_suffixes.h0100644 0000000 0000000 00000003153 13756670063 016611 0ustar000000000 0000000 /* File name suffixes. */ S_(BINPOLICY, "/policy/policy") S_(CONTEXTS_DIR, "/contexts") S_(FILE_CONTEXTS, "/contexts/files/file_contexts") S_(HOMEDIR_CONTEXTS, "/contexts/files/homedir_template") S_(DEFAULT_CONTEXTS, "/contexts/default_contexts") S_(USER_CONTEXTS, "/contexts/users/") S_(FAILSAFE_CONTEXT, "/contexts/failsafe_context") S_(DEFAULT_TYPE, "/contexts/default_type") S_(SECURETTY_TYPES, "/contexts/securetty_types") S_(BOOLEANS, "/booleans") S_(MEDIA_CONTEXTS, "/contexts/files/media") S_(REMOVABLE_CONTEXT, "/contexts/removable_context") S_(CUSTOMIZABLE_TYPES, "/contexts/customizable_types") S_(USERS_DIR, "/users/") S_(SEUSERS, "/seusers") S_(TRANSLATIONS, "/setrans.conf") S_(NETFILTER_CONTEXTS, "/contexts/netfilter_contexts") S_(FILE_CONTEXTS_HOMEDIR, "/contexts/files/file_contexts.homedirs") S_(FILE_CONTEXTS_LOCAL, "/contexts/files/file_contexts.local") S_(X_CONTEXTS, "/contexts/x_contexts") S_(COLORS, "/secolor.conf") S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context") S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context") S_(LXC_CONTEXTS, "/contexts/lxc_contexts") S_(OPENRC_CONTEXTS, "/contexts/openrc_contexts") S_(OPENSSH_CONTEXTS, "/contexts/openssh_contexts") S_(SNAPPERD_CONTEXTS, "/contexts/snapperd_contexts") S_(SYSTEMD_CONTEXTS, "/contexts/systemd_contexts") S_(FILE_CONTEXT_SUBS, "/contexts/files/file_contexts.subs") S_(FILE_CONTEXT_SUBS_DIST, "/contexts/files/file_contexts.subs_dist") S_(SEPGSQL_CONTEXTS, "/contexts/sepgsql_contexts") S_(BOOLEAN_SUBS, "/booleans.subs_dist") libselinux/src/freecon.c0100644 0000000 0000000 00000000230 13756670063 014347 0ustar000000000 0000000 #include #include "selinux_internal.h" #include #include void freecon(char * con) { free(con); } hidden_def(freecon) libselinux/src/freeconary.c0100644 0000000 0000000 00000000364 13756670063 015073 0ustar000000000 0000000 #include #include "selinux_internal.h" #include #include void freeconary(char ** con) { char **ptr; if (!con) return; for (ptr = con; *ptr; ptr++) { free(*ptr); } free(con); } hidden_def(freeconary) libselinux/src/fsetfilecon.c0100644 0000000 0000000 00000001444 13756670063 015237 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" int fsetfilecon_raw(int fd, const char * context) { int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); if (rc < 0 && errno == ENOTSUP) { char * ccontext = NULL; int err = errno; if ((fgetfilecon_raw(fd, &ccontext) >= 0) && (strcmp(context,ccontext) == 0)) { rc = 0; } else { errno = err; } freecon(ccontext); } return rc; } hidden_def(fsetfilecon_raw) int fsetfilecon(int fd, const char *context) { int ret; char * rcontext; if (selinux_trans_to_raw_context(context, &rcontext)) return -1; ret = fsetfilecon_raw(fd, rcontext); freecon(rcontext); return ret; } libselinux/src/get_context_list.c0100644 0000000 0000000 00000024624 13756670063 016321 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "context_internal.h" #include "get_context_list_internal.h" int get_default_context_with_role(const char *user, const char *role, char * fromcon, char ** newcon) { char **conary; char **ptr; context_t con; const char *role2; int rc; rc = get_ordered_context_list(user, fromcon, &conary); if (rc <= 0) return -1; for (ptr = conary; *ptr; ptr++) { con = context_new(*ptr); if (!con) continue; role2 = context_role_get(con); if (role2 && !strcmp(role, role2)) { context_free(con); break; } context_free(con); } rc = -1; if (!(*ptr)) { errno = EINVAL; goto out; } *newcon = strdup(*ptr); if (!(*newcon)) goto out; rc = 0; out: freeconary(conary); return rc; } hidden_def(get_default_context_with_role) int get_default_context_with_rolelevel(const char *user, const char *role, const char *level, char * fromcon, char ** newcon) { int rc = 0; int freefrom = 0; context_t con; char *newfromcon; if (!level) return get_default_context_with_role(user, role, fromcon, newcon); if (!fromcon) { rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } rc = -1; con = context_new(fromcon); if (!con) goto out; if (context_range_set(con, level)) goto out; newfromcon = context_str(con); if (!newfromcon) goto out; rc = get_default_context_with_role(user, role, newfromcon, newcon); out: context_free(con); if (freefrom) freecon(fromcon); return rc; } int get_default_context(const char *user, char * fromcon, char ** newcon) { char **conary; int rc; rc = get_ordered_context_list(user, fromcon, &conary); if (rc <= 0) return -1; *newcon = strdup(conary[0]); freeconary(conary); if (!(*newcon)) return -1; return 0; } static int find_partialcon(char ** list, unsigned int nreach, char *part) { const char *conrole, *contype; char *partrole, *parttype, *ptr; context_t con; unsigned int i; partrole = part; ptr = part; while (*ptr && !isspace(*ptr) && *ptr != ':') ptr++; if (*ptr != ':') return -1; *ptr++ = 0; parttype = ptr; while (*ptr && !isspace(*ptr) && *ptr != ':') ptr++; *ptr = 0; for (i = 0; i < nreach; i++) { con = context_new(list[i]); if (!con) return -1; conrole = context_role_get(con); contype = context_type_get(con); if (!conrole || !contype) { context_free(con); return -1; } if (!strcmp(conrole, partrole) && !strcmp(contype, parttype)) { context_free(con); return i; } context_free(con); } return -1; } static int get_context_order(FILE * fp, char * fromcon, char ** reachable, unsigned int nreach, unsigned int *ordering, unsigned int *nordered) { char *start, *end = NULL; char *line = NULL; size_t line_len = 0; ssize_t len; int found = 0; const char *fromrole, *fromtype; char *linerole, *linetype; unsigned int i; context_t con; int rc; errno = -EINVAL; /* Extract the role and type of the fromcon for matching. User identity and MLS range can be variable. */ con = context_new(fromcon); if (!con) return -1; fromrole = context_role_get(con); fromtype = context_type_get(con); if (!fromrole || !fromtype) { context_free(con); return -1; } while ((len = getline(&line, &line_len, fp)) > 0) { if (line[len - 1] == '\n') line[len - 1] = 0; /* Skip leading whitespace. */ start = line; while (*start && isspace(*start)) start++; if (!(*start)) continue; /* Find the end of the (partial) fromcon in the line. */ end = start; while (*end && !isspace(*end)) end++; if (!(*end)) continue; /* Check for a match. */ linerole = start; while (*start && !isspace(*start) && *start != ':') start++; if (*start != ':') continue; *start = 0; linetype = ++start; while (*start && !isspace(*start) && *start != ':') start++; if (!(*start)) continue; *start = 0; if (!strcmp(fromrole, linerole) && !strcmp(fromtype, linetype)) { found = 1; break; } } if (!found) { errno = ENOENT; rc = -1; goto out; } start = ++end; while (*start) { /* Skip leading whitespace */ while (*start && isspace(*start)) start++; if (!(*start)) break; /* Find the end of this partial context. */ end = start; while (*end && !isspace(*end)) end++; if (*end) *end++ = 0; /* Check for a match in the reachable list. */ rc = find_partialcon(reachable, nreach, start); if (rc < 0) { /* No match, skip it. */ start = end; continue; } /* If a match is found and the entry is not already ordered (e.g. due to prior match in prior config file), then set the ordering for it. */ i = rc; if (ordering[i] == nreach) ordering[i] = (*nordered)++; start = end; } rc = 0; out: context_free(con); free(line); return rc; } static int get_failsafe_context(const char *user, char ** newcon) { FILE *fp; char buf[255], *ptr; size_t plen, nlen; int rc; fp = fopen(selinux_failsafe_context_path(), "re"); if (!fp) return -1; ptr = fgets_unlocked(buf, sizeof buf, fp); fclose(fp); if (!ptr) return -1; plen = strlen(ptr); if (buf[plen - 1] == '\n') buf[plen - 1] = 0; nlen = strlen(user) + 1 + plen + 1; *newcon = malloc(nlen); if (!(*newcon)) return -1; rc = snprintf(*newcon, nlen, "%s:%s", user, ptr); if (rc < 0 || (size_t) rc >= nlen) { free(*newcon); *newcon = 0; return -1; } /* If possible, check the context to catch errors early rather than waiting until the caller tries to use setexeccon on the context. But this may not always be possible, e.g. if selinuxfs isn't mounted. */ if (security_check_context(*newcon) && errno != ENOENT) { free(*newcon); *newcon = 0; return -1; } return 0; } struct context_order { char * con; unsigned int order; }; static int order_compare(const void *A, const void *B) { const struct context_order *c1 = A, *c2 = B; if (c1->order < c2->order) return -1; else if (c1->order > c2->order) return 1; return strcmp(c1->con, c2->con); } int get_ordered_context_list_with_level(const char *user, const char *level, char * fromcon, char *** list) { int rc; int freefrom = 0; context_t con; char *newfromcon; if (!level) return get_ordered_context_list(user, fromcon, list); if (!fromcon) { rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } rc = -1; con = context_new(fromcon); if (!con) goto out; if (context_range_set(con, level)) goto out; newfromcon = context_str(con); if (!newfromcon) goto out; rc = get_ordered_context_list(user, newfromcon, list); out: context_free(con); if (freefrom) freecon(fromcon); return rc; } hidden_def(get_ordered_context_list_with_level) int get_default_context_with_level(const char *user, const char *level, char * fromcon, char ** newcon) { char **conary; int rc; rc = get_ordered_context_list_with_level(user, level, fromcon, &conary); if (rc <= 0) return -1; *newcon = strdup(conary[0]); freeconary(conary); if (!(*newcon)) return -1; return 0; } int get_ordered_context_list(const char *user, char * fromcon, char *** list) { char **reachable = NULL; unsigned int *ordering = NULL; struct context_order *co = NULL; char **ptr; int rc = 0; unsigned int nreach = 0, nordered = 0, freefrom = 0, i; FILE *fp; char *fname = NULL; size_t fname_len; const char *user_contexts_path = selinux_user_contexts_path(); if (!fromcon) { /* Get the current context and use it for the starting context */ rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } /* Determine the set of reachable contexts for the user. */ rc = security_compute_user(fromcon, user, &reachable); if (rc < 0) goto failsafe; nreach = 0; for (ptr = reachable; *ptr; ptr++) nreach++; if (!nreach) goto failsafe; /* Initialize ordering array. */ ordering = malloc(nreach * sizeof(unsigned int)); if (!ordering) goto failsafe; for (i = 0; i < nreach; i++) ordering[i] = nreach; /* Determine the ordering to apply from the optional per-user config and from the global config. */ fname_len = strlen(user_contexts_path) + strlen(user) + 2; fname = malloc(fname_len); if (!fname) goto failsafe; snprintf(fname, fname_len, "%s%s", user_contexts_path, user); fp = fopen(fname, "re"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); rc = get_context_order(fp, fromcon, reachable, nreach, ordering, &nordered); fclose(fp); if (rc < 0 && errno != ENOENT) { fprintf(stderr, "%s: error in processing configuration file %s\n", __FUNCTION__, fname); /* Fall through, try global config */ } } free(fname); fp = fopen(selinux_default_context_path(), "re"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); rc = get_context_order(fp, fromcon, reachable, nreach, ordering, &nordered); fclose(fp); if (rc < 0 && errno != ENOENT) { fprintf(stderr, "%s: error in processing configuration file %s\n", __FUNCTION__, selinux_default_context_path()); /* Fall through */ } rc = 0; } if (!nordered) goto failsafe; /* Apply the ordering. */ co = malloc(nreach * sizeof(struct context_order)); if (!co) goto failsafe; for (i = 0; i < nreach; i++) { co[i].con = reachable[i]; co[i].order = ordering[i]; } qsort(co, nreach, sizeof(struct context_order), order_compare); for (i = 0; i < nreach; i++) reachable[i] = co[i].con; free(co); /* Only report the ordered entries to the caller. */ if (nordered <= nreach) { for (i = nordered; i < nreach; i++) free(reachable[i]); reachable[nordered] = NULL; rc = nordered; } out: if (rc > 0) *list = reachable; else freeconary(reachable); free(ordering); if (freefrom) freecon(fromcon); return rc; failsafe: /* Unable to determine a reachable context list, try to fall back to the "failsafe" context to at least permit root login for emergency recovery if possible. */ freeconary(reachable); reachable = malloc(2 * sizeof(char *)); if (!reachable) { rc = -1; goto out; } reachable[0] = reachable[1] = 0; rc = get_failsafe_context(user, &reachable[0]); if (rc < 0) { freeconary(reachable); reachable = NULL; goto out; } rc = 1; /* one context in the list */ goto out; } hidden_def(get_ordered_context_list) libselinux/src/get_context_list_internal.h0100644 0000000 0000000 00000000305 13756670063 020210 0ustar000000000 0000000 #include #include "dso.h" hidden_proto(get_ordered_context_list) hidden_proto(get_ordered_context_list_with_level) hidden_proto(get_default_context_with_role) libselinux/src/get_default_type.c0100644 0000000 0000000 00000002223 13756670063 016256 0ustar000000000 0000000 #include #include #include #include #include "get_default_type_internal.h" #include static int find_default_type(FILE * fp, const char *role, char **type); int get_default_type(const char *role, char **type) { FILE *fp = NULL; fp = fopen(selinux_default_type_path(), "re"); if (!fp) return -1; if (find_default_type(fp, role, type) < 0) { fclose(fp); return -1; } fclose(fp); return 0; } static int find_default_type(FILE * fp, const char *role, char **type) { char buf[250]; const char *ptr = "", *end; char *t; size_t len; int found = 0; len = strlen(role); while (!feof_unlocked(fp)) { if (!fgets_unlocked(buf, sizeof buf, fp)) { errno = EINVAL; return -1; } if (buf[strlen(buf) - 1]) buf[strlen(buf) - 1] = 0; ptr = buf; while (*ptr && isspace(*ptr)) ptr++; if (!(*ptr)) continue; if (!strncmp(role, ptr, len)) { end = ptr + len; if (*end == ':') { found = 1; ptr = ++end; break; } } } if (!found) { errno = EINVAL; return -1; } t = malloc(strlen(buf) - len); if (!t) return -1; strcpy(t, ptr); *type = t; return 0; } libselinux/src/get_default_type_internal.h0100644 0000000 0000000 00000000140 13756670063 020153 0ustar000000000 0000000 #include #include "dso.h" hidden_proto(selinux_default_type_path) libselinux/src/get_initial_context.c0100644 0000000 0000000 00000002333 13756670063 016770 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #define SELINUX_INITCON_DIR "/initial_contexts/" int security_get_initial_context_raw(const char * name, char ** con) { char path[PATH_MAX]; char *buf; size_t size; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s%s%s", selinux_mnt, SELINUX_INITCON_DIR, name); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } memset(buf, 0, size); ret = read(fd, buf, size - 1); if (ret < 0) goto out2; *con = strdup(buf); if (!(*con)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: close(fd); return ret; } hidden_def(security_get_initial_context_raw) int security_get_initial_context(const char * name, char ** con) { int ret; char * rcon; ret = security_get_initial_context_raw(name, &rcon); if (!ret) { ret = selinux_raw_to_trans_context(rcon, con); freecon(rcon); } return ret; } hidden_def(security_get_initial_context) libselinux/src/getenforce.c0100644 0000000 0000000 00000001276 13756670063 015062 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_getenforce(void) { int fd, ret, enforce = 0; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/enforce", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; memset(buf, 0, sizeof buf); ret = read(fd, buf, sizeof buf - 1); close(fd); if (ret < 0) return -1; if (sscanf(buf, "%d", &enforce) != 1) return -1; return !!enforce; } hidden_def(security_getenforce) libselinux/src/getfilecon.c0100644 0000000 0000000 00000002402 13756670063 015050 0ustar000000000 0000000 #include #include #include #include "selinux_internal.h" #include #include #include #include "policy.h" int getfilecon_raw(const char *path, char ** context) { char *buf; ssize_t size; ssize_t ret; size = INITCONTEXTLEN + 1; buf = malloc(size); if (!buf) return -1; memset(buf, 0, size); ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1); if (ret < 0 && errno == ERANGE) { char *newbuf; size = getxattr(path, XATTR_NAME_SELINUX, NULL, 0); if (size < 0) goto out; size++; newbuf = realloc(buf, size); if (!newbuf) goto out; buf = newbuf; memset(buf, 0, size); ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1); } out: if (ret == 0) { /* Re-map empty attribute values to errors. */ errno = ENOTSUP; ret = -1; } if (ret < 0) free(buf); else *context = buf; return ret; } hidden_def(getfilecon_raw) int getfilecon(const char *path, char ** context) { int ret; char * rcontext = NULL; *context = NULL; ret = getfilecon_raw(path, &rcontext); if (ret > 0) { ret = selinux_raw_to_trans_context(rcontext, context); freecon(rcontext); } if (ret >= 0 && *context) return strlen(*context) + 1; return ret; } hidden_def(getfilecon) libselinux/src/getpeercon.c0100644 0000000 0000000 00000001761 13756670063 015073 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #ifndef SO_PEERSEC #define SO_PEERSEC 31 #endif int getpeercon_raw(int fd, char ** context) { char *buf; socklen_t size; ssize_t ret; size = INITCONTEXTLEN + 1; buf = malloc(size); if (!buf) return -1; memset(buf, 0, size); ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size); if (ret < 0 && errno == ERANGE) { char *newbuf; newbuf = realloc(buf, size); if (!newbuf) goto out; buf = newbuf; memset(buf, 0, size); ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size); } out: if (ret < 0) free(buf); else *context = buf; return ret; } hidden_def(getpeercon_raw) int getpeercon(int fd, char ** context) { int ret; char * rcontext; ret = getpeercon_raw(fd, &rcontext); if (!ret) { ret = selinux_raw_to_trans_context(rcontext, context); freecon(rcontext); } return ret; } libselinux/src/init.c0100644 0000000 0000000 00000005702 13756670063 013702 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dso.h" #include "policy.h" #include "selinux_internal.h" #include "setrans_internal.h" char *selinux_mnt = NULL; int selinux_page_size = 0; int has_selinux_config = 0; /* Verify the mount point for selinux file system has a selinuxfs. If the file system: * Exist, * Is mounted with an selinux file system, * The file system is read/write * then set this as the default file system. */ static int verify_selinuxmnt(const char *mnt) { struct statfs sfbuf; int rc; do { rc = statfs(mnt, &sfbuf); } while (rc < 0 && errno == EINTR); if (rc == 0) { if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) { struct statvfs vfsbuf; rc = statvfs(mnt, &vfsbuf); if (rc == 0) { if (!(vfsbuf.f_flag & ST_RDONLY)) { set_selinuxmnt(mnt); } return 0; } } } return -1; } int selinuxfs_exists(void) { int exists = 0; FILE *fp = NULL; char *buf = NULL; size_t len; ssize_t num; fp = fopen("/proc/filesystems", "re"); if (!fp) return 1; /* Fail as if it exists */ __fsetlocking(fp, FSETLOCKING_BYCALLER); num = getline(&buf, &len, fp); while (num != -1) { if (strstr(buf, SELINUXFS)) { exists = 1; break; } num = getline(&buf, &len, fp); } free(buf); fclose(fp); return exists; } hidden_def(selinuxfs_exists) static void init_selinuxmnt(void) { char *buf=NULL, *p; FILE *fp=NULL; size_t len; ssize_t num; if (selinux_mnt) return; if (verify_selinuxmnt(SELINUXMNT) == 0) return; if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return; /* Drop back to detecting it the long way. */ if (!selinuxfs_exists()) goto out; /* At this point, the usual spot doesn't have an selinuxfs so * we look around for it */ fp = fopen("/proc/mounts", "re"); if (!fp) goto out; __fsetlocking(fp, FSETLOCKING_BYCALLER); while ((num = getline(&buf, &len, fp)) != -1) { char *tmp; p = strchr(buf, ' '); if (!p) goto out; p++; tmp = strchr(p, ' '); if (!tmp) goto out; if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) { *tmp = '\0'; break; } } /* If we found something, dup it */ if (num > 0) verify_selinuxmnt(p); out: free(buf); if (fp) fclose(fp); return; } void fini_selinuxmnt(void) { free(selinux_mnt); selinux_mnt = NULL; } hidden_def(fini_selinuxmnt) void set_selinuxmnt(const char *mnt) { selinux_mnt = strdup(mnt); } hidden_def(set_selinuxmnt) static void init_lib(void) __attribute__ ((constructor)); static void init_lib(void) { selinux_page_size = sysconf(_SC_PAGE_SIZE); init_selinuxmnt(); #ifndef ANDROID has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0); #endif } static void fini_lib(void) __attribute__ ((destructor)); static void fini_lib(void) { fini_selinuxmnt(); } libselinux/src/is_customizable_type.c0100644 0000000 0000000 00000003124 13756670063 017170 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "context_internal.h" static int get_customizable_type_list(char *** retlist) { FILE *fp; char *buf; unsigned int ctr = 0, i; char **list = NULL; fp = fopen(selinux_customizable_types_path(), "re"); if (!fp) return -1; buf = malloc(selinux_page_size); if (!buf) { fclose(fp); return -1; } while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) { ctr++; } rewind(fp); if (ctr) { list = (char **) calloc(sizeof(char *), ctr + 1); if (list) { i = 0; while (fgets_unlocked(buf, selinux_page_size, fp) && i < ctr) { buf[strlen(buf) - 1] = 0; list[i] = (char *) strdup(buf); if (!list[i]) { unsigned int j; for (j = 0; j < i; j++) free(list[j]); free(list); list = NULL; break; } i++; } } } fclose(fp); free(buf); if (!list) return -1; *retlist = list; return 0; } static char **customizable_list = NULL; int is_context_customizable(const char * scontext) { int i; const char *type; context_t c; if (!customizable_list) { if (get_customizable_type_list(&customizable_list) != 0) return -1; } c = context_new(scontext); if (!c) return -1; type = context_type_get(c); if (!type) { context_free(c); return -1; } for (i = 0; customizable_list[i]; i++) { if (strcmp(customizable_list[i], type) == 0) { context_free(c); return 1; } } context_free(c); return 0; } libselinux/src/label.c0100644 0000000 0000000 00000016660 13756670063 014023 0ustar000000000 0000000 /* * Generalized labeling frontend for userspace object managers. * * Author : Eamon Walsh */ #include #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef NO_FILE_BACKEND #define CONFIG_FILE_BACKEND(fnptr) NULL #else #define CONFIG_FILE_BACKEND(fnptr) &fnptr #endif #ifdef NO_MEDIA_BACKEND #define CONFIG_MEDIA_BACKEND(fnptr) NULL #else #define CONFIG_MEDIA_BACKEND(fnptr) &fnptr #endif #ifdef NO_X_BACKEND #define CONFIG_X_BACKEND(fnptr) NULL #else #define CONFIG_X_BACKEND(fnptr) &fnptr #endif #ifdef NO_DB_BACKEND #define CONFIG_DB_BACKEND(fnptr) NULL #else #define CONFIG_DB_BACKEND(fnptr) &fnptr #endif #ifdef NO_ANDROID_BACKEND #define CONFIG_ANDROID_BACKEND(fnptr) NULL #else #define CONFIG_ANDROID_BACKEND(fnptr) (&(fnptr)) #endif typedef int (*selabel_initfunc)(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts); static selabel_initfunc initfuncs[] = { CONFIG_FILE_BACKEND(selabel_file_init), CONFIG_MEDIA_BACKEND(selabel_media_init), CONFIG_X_BACKEND(selabel_x_init), CONFIG_DB_BACKEND(selabel_db_init), CONFIG_ANDROID_BACKEND(selabel_property_init), CONFIG_ANDROID_BACKEND(selabel_service_init), }; static inline struct selabel_digest *selabel_is_digest_set (const struct selinux_opt *opts, unsigned n, struct selabel_digest *entry) { struct selabel_digest *digest = NULL; while (n--) { if (opts[n].type == SELABEL_OPT_DIGEST && opts[n].value == (char *)1) { digest = calloc(1, sizeof(*digest)); if (!digest) goto err; digest->digest = calloc(1, DIGEST_SPECFILE_SIZE + 1); if (!digest->digest) goto err; digest->specfile_list = calloc(DIGEST_FILES_MAX, sizeof(char *)); if (!digest->specfile_list) goto err; entry = digest; return entry; } } return NULL; err: if (digest) { free(digest->digest); free(digest->specfile_list); free(digest); } return NULL; } static void selabel_digest_fini(struct selabel_digest *ptr) { int i; free(ptr->digest); free(ptr->hashbuf); if (ptr->specfile_list) { for (i = 0; ptr->specfile_list[i]; i++) free(ptr->specfile_list[i]); free(ptr->specfile_list); } free(ptr); } /* * Validation functions */ static inline int selabel_is_validate_set(const struct selinux_opt *opts, unsigned n) { while (n--) if (opts[n].type == SELABEL_OPT_VALIDATE) return !!opts[n].value; return 0; } int selabel_validate(struct selabel_handle *rec, struct selabel_lookup_rec *contexts) { int rc = 0; if (!rec->validating || contexts->validated) goto out; rc = selinux_validate(&contexts->ctx_raw); if (rc < 0) goto out; contexts->validated = 1; out: return rc; } /* Public API helpers */ static int selabel_fini(struct selabel_handle *rec, struct selabel_lookup_rec *lr, int translating) { char *path = NULL; if (rec->spec_files) path = rec->spec_files[0]; if (compat_validate(rec, lr, path, lr->lineno)) return -1; if (translating && !lr->ctx_trans && selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans)) return -1; return 0; } static struct selabel_lookup_rec * selabel_lookup_common(struct selabel_handle *rec, int translating, const char *key, int type) { struct selabel_lookup_rec *lr; if (key == NULL) { errno = EINVAL; return NULL; } lr = rec->func_lookup(rec, key, type); if (!lr) return NULL; if (selabel_fini(rec, lr, translating)) return NULL; return lr; } static struct selabel_lookup_rec * selabel_lookup_bm_common(struct selabel_handle *rec, int translating, const char *key, int type, const char **aliases) { struct selabel_lookup_rec *lr; if (key == NULL) { errno = EINVAL; return NULL; } lr = rec->func_lookup_best_match(rec, key, aliases, type); if (!lr) return NULL; if (selabel_fini(rec, lr, translating)) return NULL; return lr; } /* * Public API */ struct selabel_handle *selabel_open(unsigned int backend, const struct selinux_opt *opts, unsigned nopts) { struct selabel_handle *rec = NULL; if (backend >= ARRAY_SIZE(initfuncs)) { errno = EINVAL; goto out; } if (!initfuncs[backend]) { errno = ENOTSUP; goto out; } rec = (struct selabel_handle *)malloc(sizeof(*rec)); if (!rec) goto out; memset(rec, 0, sizeof(*rec)); rec->backend = backend; rec->validating = selabel_is_validate_set(opts, nopts); rec->digest = selabel_is_digest_set(opts, nopts, rec->digest); if ((*initfuncs[backend])(rec, opts, nopts)) { selabel_close(rec); rec = NULL; } out: return rec; } int selabel_lookup(struct selabel_handle *rec, char **con, const char *key, int type) { struct selabel_lookup_rec *lr; lr = selabel_lookup_common(rec, 1, key, type); if (!lr) return -1; *con = strdup(lr->ctx_trans); return *con ? 0 : -1; } int selabel_lookup_raw(struct selabel_handle *rec, char **con, const char *key, int type) { struct selabel_lookup_rec *lr; lr = selabel_lookup_common(rec, 0, key, type); if (!lr) return -1; *con = strdup(lr->ctx_raw); return *con ? 0 : -1; } bool selabel_partial_match(struct selabel_handle *rec, const char *key) { if (!rec->func_partial_match) { /* * If the label backend does not support partial matching, * then assume a match is possible. */ return true; } return rec->func_partial_match(rec, key); } bool selabel_hash_all_partial_matches(struct selabel_handle *rec, const char *key, uint8_t *digest) { if (!rec->func_hash_all_partial_matches) { return false; } return rec->func_hash_all_partial_matches(rec, key, digest); } int selabel_lookup_best_match(struct selabel_handle *rec, char **con, const char *key, const char **aliases, int type) { struct selabel_lookup_rec *lr; if (!rec->func_lookup_best_match) { errno = ENOTSUP; return -1; } lr = selabel_lookup_bm_common(rec, 1, key, type, aliases); if (!lr) return -1; *con = strdup(lr->ctx_trans); return *con ? 0 : -1; } int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con, const char *key, const char **aliases, int type) { struct selabel_lookup_rec *lr; if (!rec->func_lookup_best_match) { errno = ENOTSUP; return -1; } lr = selabel_lookup_bm_common(rec, 0, key, type, aliases); if (!lr) return -1; *con = strdup(lr->ctx_raw); return *con ? 0 : -1; } enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1, struct selabel_handle *h2) { if (!h1->func_cmp || h1->func_cmp != h2->func_cmp) return SELABEL_INCOMPARABLE; return h1->func_cmp(h1, h2); } int selabel_digest(struct selabel_handle *rec, unsigned char **digest, size_t *digest_len, char ***specfiles, size_t *num_specfiles) { if (!rec->digest) { errno = EINVAL; return -1; } *digest = rec->digest->digest; *digest_len = DIGEST_SPECFILE_SIZE; *specfiles = rec->digest->specfile_list; *num_specfiles = rec->digest->specfile_cnt; return 0; } void selabel_close(struct selabel_handle *rec) { size_t i; if (rec->spec_files) { for (i = 0; i < rec->spec_files_len; i++) free(rec->spec_files[i]); free(rec->spec_files); } if (rec->digest) selabel_digest_fini(rec->digest); if (rec->func_close) rec->func_close(rec); free(rec); } void selabel_stats(struct selabel_handle *rec) { rec->func_stats(rec); } libselinux/src/label_backends_android.c0100644 0000000 0000000 00000020560 13756670063 017347 0ustar000000000 0000000 /* * Property Service contexts backend for labeling Android * property keys */ #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" /* A property security context specification. */ typedef struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ char *property_key; /* property key string */ } spec_t; /* Our stored configuration */ struct saved_data { /* * The array of specifications is sorted for longest * prefix match */ spec_t *spec_arr; unsigned int nspec; /* total number of specifications */ }; static int cmp(const void *A, const void *B) { const struct spec *sp1 = A, *sp2 = B; if (strncmp(sp1->property_key, "*", 1) == 0) return 1; if (strncmp(sp2->property_key, "*", 1) == 0) return -1; size_t L1 = strlen(sp1->property_key); size_t L2 = strlen(sp2->property_key); return (L1 < L2) - (L1 > L2); } /* * Warn about duplicate specifications. Return error on different specifications. * TODO: Remove duplicate specifications. Move duplicate check to after sort * to improve performance. */ static int nodups_specs(struct saved_data *data) { int rc = 0; unsigned int ii, jj; struct spec *curr_spec, *spec_arr = data->spec_arr; for (ii = 0; ii < data->nspec; ii++) { curr_spec = &spec_arr[ii]; for (jj = ii + 1; jj < data->nspec; jj++) { if (!strcmp(spec_arr[jj].property_key, curr_spec->property_key)) { if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) { rc = -1; errno = EINVAL; selinux_log (SELINUX_ERROR, "Multiple different specifications for %s (%s and %s).\n", curr_spec->property_key, spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw); } else { selinux_log (SELINUX_WARNING, "Multiple same specifications for %s.\n", curr_spec->property_key); } } } } return rc; } static int process_line(struct selabel_handle *rec, const char *path, char *line_buf, int pass, unsigned lineno) { int items; char *prop = NULL, *context = NULL; struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int nspec = data->nspec; const char *errbuf = NULL; items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context); if (items < 0) { items = errno; selinux_log(SELINUX_ERROR, "%s: line %u error due to: %s\n", path, lineno, errbuf ?: strerror(errno)); errno = items; return -1; } if (items == 0) return items; if (items != 2) { selinux_log(SELINUX_ERROR, "%s: line %u is missing fields\n", path, lineno); free(prop); errno = EINVAL; return -1; } if (pass == 0) { free(prop); free(context); } else if (pass == 1) { /* On the second pass, process and store the specification in spec. */ spec_arr[nspec].property_key = prop; spec_arr[nspec].lr.ctx_raw = context; if (rec->validating) { if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { selinux_log(SELINUX_ERROR, "%s: line %u has invalid context %s\n", path, lineno, spec_arr[nspec].lr.ctx_raw); errno = EINVAL; return -1; } } data->nspec = ++nspec; } return 0; } static int process_file(struct selabel_handle *rec, const char *path) { struct saved_data *data = (struct saved_data *)rec->data; char line_buf[BUFSIZ]; unsigned int lineno, maxnspec, pass; struct stat sb; FILE *fp; int status = -1; unsigned int nspec; spec_t *spec_arr; /* Open the specification file. */ if ((fp = fopen(path, "re")) == NULL) return -1; if (fstat(fileno(fp), &sb) < 0) goto finish; errno = EINVAL; if (!S_ISREG(sb.st_mode)) goto finish; /* * Two passes per specification file. First is to get the size. * After the first pass, the spec array is malloced / realloced to * the appropriate size. Second pass is to populate the spec array. */ maxnspec = UINT_MAX / sizeof(spec_t); for (pass = 0; pass < 2; pass++) { nspec = 0; lineno = 0; while (fgets(line_buf, sizeof(line_buf) - 1, fp) && nspec < maxnspec) { if (process_line(rec, path, line_buf, pass, ++lineno)) goto finish; nspec++; } if (pass == 0) { if (nspec == 0) { status = 0; goto finish; } /* grow spec array if required */ spec_arr = realloc(data->spec_arr, (data->nspec + nspec) * sizeof(spec_t)); if (spec_arr == NULL) goto finish; memset(&spec_arr[data->nspec], 0, nspec * sizeof(spec_t)); data->spec_arr = spec_arr; maxnspec = nspec; rewind(fp); } } status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path); finish: fclose(fp); return status; } static void closef(struct selabel_handle *rec); static int init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned n) { struct saved_data *data = (struct saved_data *)rec->data; char **paths = NULL; size_t num_paths = 0; int status = -1; size_t i; /* Process arguments */ i = n; while (i--) { switch (opts[i].type) { case SELABEL_OPT_PATH: num_paths++; break; } } if (!num_paths) return -1; paths = calloc(num_paths, sizeof(*paths)); if (!paths) return -1; rec->spec_files = paths; rec->spec_files_len = num_paths; i = n; while (i--) { switch(opts[i].type) { case SELABEL_OPT_PATH: *paths = strdup(opts[i].value); if (*paths == NULL) goto finish; paths++; } } for (i = 0; i < num_paths; i++) { status = process_file(rec, rec->spec_files[i]); if (status) goto finish; } /* warn about duplicates after all files have been processed. */ status = nodups_specs(data); if (status) goto finish; qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp); digest_gen_hash(rec->digest); finish: if (status) closef(rec); return status; } /* * Backend interface routines */ static void closef(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec; unsigned int i; if (data->spec_arr) { for (i = 0; i < data->nspec; i++) { spec = &data->spec_arr[i]; free(spec->property_key); free(spec->lr.ctx_raw); free(spec->lr.ctx_trans); } free(data->spec_arr); } free(data); } static struct selabel_lookup_rec *property_lookup(struct selabel_handle *rec, const char *key, int __attribute__((unused)) type) { struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int i; struct selabel_lookup_rec *ret = NULL; if (!data->nspec) { errno = ENOENT; goto finish; } for (i = 0; i < data->nspec; i++) { if (strncmp(spec_arr[i].property_key, key, strlen(spec_arr[i].property_key)) == 0) { break; } if (strncmp(spec_arr[i].property_key, "*", 1) == 0) break; } if (i >= data->nspec) { /* No matching specification. */ errno = ENOENT; goto finish; } ret = &spec_arr[i].lr; finish: return ret; } static struct selabel_lookup_rec *service_lookup(struct selabel_handle *rec, const char *key, int __attribute__((unused)) type) { struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int i; struct selabel_lookup_rec *ret = NULL; if (!data->nspec) { errno = ENOENT; goto finish; } for (i = 0; i < data->nspec; i++) { if (strcmp(spec_arr[i].property_key, key) == 0) break; if (strcmp(spec_arr[i].property_key, "*") == 0) break; } if (i >= data->nspec) { /* No matching specification. */ errno = ENOENT; goto finish; } ret = &spec_arr[i].lr; finish: return ret; } static void stats(struct selabel_handle __attribute__((unused)) *rec) { selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n"); } int selabel_property_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { struct saved_data *data; data = (struct saved_data *)calloc(1, sizeof(*data)); if (!data) return -1; rec->data = data; rec->func_close = &closef; rec->func_stats = &stats; rec->func_lookup = &property_lookup; return init(rec, opts, nopts); } int selabel_service_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { struct saved_data *data; data = (struct saved_data *)calloc(1, sizeof(*data)); if (!data) return -1; rec->data = data; rec->func_close = &closef; rec->func_stats = &stats; rec->func_lookup = &service_lookup; return init(rec, opts, nopts); } libselinux/src/label_db.c0100644 0000000 0000000 00000020716 13756670063 014465 0ustar000000000 0000000 /* * Media contexts backend for DB objects * * Author: KaiGai Kohei */ #include #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" /* * Regular database object's security context interface * * It provides applications a regular security context for the given * database objects. The pair of object's name and a security context * are described in the specfile. In the default, it shall be stored * in the /etc/selinux/$POLICYTYPE/contexts/sepgsql_contexts . * (It assumes SE-PostgreSQL in the default. For other RDBMS, use the * SELABEL_OPT_PATH option to specify different specfile.) * * Each line has the following format: * * * For example: * ---------------------------------------- * # * # It is an example specfile for database obejcts * # * db_database template1 system_u:object_r:sepgsql_db_t:s0 * * db_schema *.pg_catalog system_u:object_r:sepgsql_sys_schema_t:s0 * * db_table *.pg_catalog.* system_u:object_r:sepgsql_sysobj_t:s0 * db_column *.pg_catalog.*.* system_u:object_r:sepgsql_sysobj_t:s0 * ---------------------------------------- * * All the characters after the '#' are dealt as comments. * * The first token is object class. SELABEL_DB_* declared in label.h are * corresponding to a certain database object. * * The object name/identifier is compared to the given key. * A database object can have its own namespace hierarchy. * In the case of SE-PgSQL, database is the top level object, and schema * is deployed just under a database. A schema can contains various kind * of objects, such as tables, procedures and so on. * Thus, when we lookup an expected security context for a table of * "pg_class", it is necessary to assume selabel_lookup() is called with * "postgres.pg_catalog.pg_class", not just a "pg_class". * * Wildcards ('*' or '?') are available on the patterns, so if you want * to match a table within any schema, you should set '*' on the upper * namespaces of the table. * * The structure of namespace depends on RDBMS. * For example, Trusted-RUBIX has an idea of "catalog" which performs * as a namespace between a database and individual schemas. In this * case, a table has upper three layers. */ /* * spec_t : It holds a pair of a key and an expected security context */ typedef struct spec { struct selabel_lookup_rec lr; char *key; int type; int matches; } spec_t; /* * catalog_t : An array of spec_t */ typedef struct catalog { unsigned int nspec; /* number of specs in use */ unsigned int limit; /* physical limitation of specs[] */ spec_t specs[0]; } catalog_t; /* * Helper function to parse a line read from the specfile */ static int process_line(const char *path, char *line_buf, unsigned int line_num, catalog_t *catalog) { spec_t *spec = &catalog->specs[catalog->nspec]; char *type, *key, *context, *temp; int items; /* Cut off comments */ temp = strchr(line_buf, '#'); if (temp) *temp = '\0'; /* * Every entry must have the following format * */ type = key = context = temp = NULL; items = sscanf(line_buf, "%ms %ms %ms %ms", &type, &key, &context, &temp); if (items != 3) { if (items > 0) selinux_log(SELINUX_WARNING, "%s: line %u has invalid format, skipped", path, line_num); goto skip; } /* * Set up individual spec entry */ memset(spec, 0, sizeof(spec_t)); if (!strcmp(type, "db_database")) spec->type = SELABEL_DB_DATABASE; else if (!strcmp(type, "db_schema")) spec->type = SELABEL_DB_SCHEMA; else if (!strcmp(type, "db_table")) spec->type = SELABEL_DB_TABLE; else if (!strcmp(type, "db_column")) spec->type = SELABEL_DB_COLUMN; else if (!strcmp(type, "db_sequence")) spec->type = SELABEL_DB_SEQUENCE; else if (!strcmp(type, "db_view")) spec->type = SELABEL_DB_VIEW; else if (!strcmp(type, "db_procedure")) spec->type = SELABEL_DB_PROCEDURE; else if (!strcmp(type, "db_blob")) spec->type = SELABEL_DB_BLOB; else if (!strcmp(type, "db_tuple")) spec->type = SELABEL_DB_TUPLE; else if (!strcmp(type, "db_language")) spec->type = SELABEL_DB_LANGUAGE; else if (!strcmp(type, "db_exception")) spec->type = SELABEL_DB_EXCEPTION; else if (!strcmp(type, "db_datatype")) spec->type = SELABEL_DB_DATATYPE; else { selinux_log(SELINUX_WARNING, "%s: line %u has invalid object type %s\n", path, line_num, type); goto skip; } free(type); spec->key = key; spec->lr.ctx_raw = context; catalog->nspec++; return 0; skip: free(type); free(key); free(context); free(temp); return 0; } /* * selabel_close() handler */ static void db_close(struct selabel_handle *rec) { catalog_t *catalog = (catalog_t *)rec->data; spec_t *spec; unsigned int i; for (i = 0; i < catalog->nspec; i++) { spec = &catalog->specs[i]; free(spec->key); free(spec->lr.ctx_raw); free(spec->lr.ctx_trans); } free(catalog); } /* * selabel_lookup() handler */ static struct selabel_lookup_rec * db_lookup(struct selabel_handle *rec, const char *key, int type) { catalog_t *catalog = (catalog_t *)rec->data; spec_t *spec; unsigned int i; for (i = 0; i < catalog->nspec; i++) { spec = &catalog->specs[i]; if (spec->type != type) continue; if (!fnmatch(spec->key, key, 0)) { spec->matches++; return &spec->lr; } } /* No found */ errno = ENOENT; return NULL; } /* * selabel_stats() handler */ static void db_stats(struct selabel_handle *rec) { catalog_t *catalog = (catalog_t *)rec->data; unsigned int i, total = 0; for (i = 0; i < catalog->nspec; i++) total += catalog->specs[i].matches; selinux_log(SELINUX_INFO, "%u entries, %u matches made\n", catalog->nspec, total); } /* * selabel_open() handler */ static catalog_t * db_init(const struct selinux_opt *opts, unsigned nopts, struct selabel_handle *rec) { catalog_t *catalog; FILE *filp; const char *path = NULL; char *line_buf = NULL; size_t line_len = 0; unsigned int line_num = 0; unsigned int i; struct stat sb; /* * Initialize catalog data structure */ catalog = malloc(sizeof(catalog_t) + 32 * sizeof(spec_t)); if (!catalog) return NULL; catalog->limit = 32; catalog->nspec = 0; /* * Process arguments * * SELABEL_OPT_PATH: * It allows to specify an alternative specification file instead of * the default one. If RDBMS is not SE-PostgreSQL, it may need to * specify an explicit specfile for database objects. */ while (nopts--) { switch (opts[nopts].type) { case SELABEL_OPT_PATH: path = opts[nopts].value; break; } } /* * Open the specification file */ if (!path) path = selinux_sepgsql_context_path(); if ((filp = fopen(path, "rb")) == NULL) { free(catalog); return NULL; } if (fstat(fileno(filp), &sb) < 0) { free(catalog); fclose(filp); return NULL; } if (!S_ISREG(sb.st_mode)) { free(catalog); fclose(filp); errno = EINVAL; return NULL; } rec->spec_file = strdup(path); /* * Parse for each lines */ while (getline(&line_buf, &line_len, filp) > 0) { /* * Expand catalog array, if necessary */ if (catalog->limit == catalog->nspec) { size_t length; unsigned int new_limit = 2 * catalog->limit; catalog_t *new_catalog; length = sizeof(catalog_t) + new_limit * sizeof(spec_t); new_catalog = realloc(catalog, length); if (!new_catalog) goto out_error; catalog = new_catalog; catalog->limit = new_limit; } /* * Parse a line */ if (process_line(path, line_buf, ++line_num, catalog) < 0) goto out_error; } free(line_buf); if (digest_add_specfile(rec->digest, filp, NULL, sb.st_size, path) < 0) goto out_error; digest_gen_hash(rec->digest); fclose(filp); return catalog; out_error: for (i = 0; i < catalog->nspec; i++) { spec_t *spec = &catalog->specs[i]; free(spec->key); free(spec->lr.ctx_raw); free(spec->lr.ctx_trans); } free(catalog); fclose(filp); return NULL; } /* * Initialize selabel_handle and load the entries of specfile */ int selabel_db_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { rec->func_close = &db_close; rec->func_lookup = &db_lookup; rec->func_stats = &db_stats; rec->data = db_init(opts, nopts, rec); return !rec->data ? -1 : 0; } libselinux/src/label_file.c0100644 0000000 0000000 00000067737 13756670063 015035 0ustar000000000 0000000 /* * File contexts backend for labeling system * * Author : Eamon Walsh * Author : Stephen Smalley */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" #include "label_file.h" /* * Internals, mostly moved over from matchpathcon.c */ /* return the length of the text that is the stem of a file name */ static int get_stem_from_file_name(const char *const buf) { const char *tmp = strchr(buf + 1, '/'); if (!tmp) return 0; return tmp - buf; } /* find the stem of a file name, returns the index into stem_arr (or -1 if * there is no match - IE for a file in the root directory or a regex that is * too complex for us). */ static int find_stem_from_file(struct saved_data *data, const char *key) { int i; int stem_len = get_stem_from_file_name(key); if (!stem_len) return -1; for (i = 0; i < data->num_stems; i++) { if (stem_len == data->stem_arr[i].len && !strncmp(key, data->stem_arr[i].buf, stem_len)) { return i; } } return -1; } /* * Warn about duplicate specifications. */ static int nodups_specs(struct saved_data *data, const char *path) { int rc = 0; unsigned int ii, jj; struct spec *curr_spec, *spec_arr = data->spec_arr; for (ii = 0; ii < data->nspec; ii++) { curr_spec = &spec_arr[ii]; for (jj = ii + 1; jj < data->nspec; jj++) { if ((!strcmp(spec_arr[jj].regex_str, curr_spec->regex_str)) && (!spec_arr[jj].mode || !curr_spec->mode || spec_arr[jj].mode == curr_spec->mode)) { rc = -1; errno = EINVAL; if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) { COMPAT_LOG (SELINUX_ERROR, "%s: Multiple different specifications for %s (%s and %s).\n", path, curr_spec->regex_str, spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw); } else { COMPAT_LOG (SELINUX_ERROR, "%s: Multiple same specifications for %s.\n", path, curr_spec->regex_str); } } } } return rc; } static int process_text_file(FILE *fp, const char *prefix, struct selabel_handle *rec, const char *path) { int rc; size_t line_len; unsigned int lineno = 0; char *line_buf = NULL; while (getline(&line_buf, &line_len, fp) > 0) { rc = process_line(rec, path, prefix, line_buf, ++lineno); if (rc) goto out; } rc = 0; out: free(line_buf); return rc; } static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, const char *path) { struct saved_data *data = (struct saved_data *)rec->data; int rc; char *addr, *str_buf; int *stem_map; struct mmap_area *mmap_area; uint32_t i, magic, version; uint32_t entry_len, stem_map_len, regex_array_len; const char *reg_version; const char *reg_arch; char reg_arch_matches = 0; mmap_area = malloc(sizeof(*mmap_area)); if (!mmap_area) { return -1; } addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(fp), 0); if (addr == MAP_FAILED) { free(mmap_area); perror("mmap"); return -1; } /* save where we mmap'd the file to cleanup on close() */ mmap_area->addr = mmap_area->next_addr = addr; mmap_area->len = mmap_area->next_len = len; mmap_area->next = data->mmap_areas; data->mmap_areas = mmap_area; /* check if this looks like an fcontext file */ rc = next_entry(&magic, mmap_area, sizeof(uint32_t)); if (rc < 0 || magic != SELINUX_MAGIC_COMPILED_FCONTEXT) return -1; /* check if this version is higher than we understand */ rc = next_entry(&version, mmap_area, sizeof(uint32_t)); if (rc < 0 || version > SELINUX_COMPILED_FCONTEXT_MAX_VERS) return -1; reg_version = regex_version(); if (!reg_version) return -1; reg_arch = regex_arch_string(); if (!reg_arch) return -1; if (version >= SELINUX_COMPILED_FCONTEXT_PCRE_VERS) { len = strlen(reg_version); rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0) return -1; /* Check version lengths */ if (len != entry_len) return -1; /* Check if regex version mismatch */ str_buf = malloc(entry_len + 1); if (!str_buf) return -1; rc = next_entry(str_buf, mmap_area, entry_len); if (rc < 0) { free(str_buf); return -1; } str_buf[entry_len] = '\0'; if ((strcmp(str_buf, reg_version) != 0)) { free(str_buf); return -1; } free(str_buf); if (version >= SELINUX_COMPILED_FCONTEXT_REGEX_ARCH) { len = strlen(reg_arch); rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0) return -1; /* Check arch string lengths */ if (len != entry_len) { /* * Skip the entry and conclude that we have * a mismatch, which is not fatal. */ next_entry(NULL, mmap_area, entry_len); goto end_arch_check; } /* Check if arch string mismatch */ str_buf = malloc(entry_len + 1); if (!str_buf) return -1; rc = next_entry(str_buf, mmap_area, entry_len); if (rc < 0) { free(str_buf); return -1; } str_buf[entry_len] = '\0'; reg_arch_matches = strcmp(str_buf, reg_arch) == 0; free(str_buf); } } end_arch_check: /* allocate the stems_data array */ rc = next_entry(&stem_map_len, mmap_area, sizeof(uint32_t)); if (rc < 0) return -1; /* * map indexed by the stem # in the mmap file and contains the stem * number in the data stem_arr */ stem_map = calloc(stem_map_len, sizeof(*stem_map)); if (!stem_map) return -1; for (i = 0; i < stem_map_len; i++) { char *buf; uint32_t stem_len; int newid; /* the length does not inlude the nul */ rc = next_entry(&stem_len, mmap_area, sizeof(uint32_t)); if (rc < 0 || !stem_len) { rc = -1; goto out; } /* Check for stem_len wrap around. */ if (stem_len < UINT32_MAX) { buf = (char *)mmap_area->next_addr; /* Check if over-run before null check. */ rc = next_entry(NULL, mmap_area, (stem_len + 1)); if (rc < 0) goto out; if (buf[stem_len] != '\0') { rc = -1; goto out; } } else { rc = -1; goto out; } /* store the mapping between old and new */ newid = find_stem(data, buf, stem_len); if (newid < 0) { newid = store_stem(data, buf, stem_len); if (newid < 0) { rc = newid; goto out; } data->stem_arr[newid].from_mmap = 1; } stem_map[i] = newid; } /* allocate the regex array */ rc = next_entry(®ex_array_len, mmap_area, sizeof(uint32_t)); if (rc < 0 || !regex_array_len) { rc = -1; goto out; } for (i = 0; i < regex_array_len; i++) { struct spec *spec; int32_t stem_id, meta_chars; uint32_t mode = 0, prefix_len = 0; rc = grow_specs(data); if (rc < 0) goto out; spec = &data->spec_arr[data->nspec]; spec->from_mmap = 1; /* Process context */ rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0 || !entry_len) { rc = -1; goto out; } str_buf = malloc(entry_len); if (!str_buf) { rc = -1; goto out; } rc = next_entry(str_buf, mmap_area, entry_len); if (rc < 0) { free(str_buf); goto out; } if (str_buf[entry_len - 1] != '\0') { free(str_buf); rc = -1; goto out; } spec->lr.ctx_raw = str_buf; if (strcmp(spec->lr.ctx_raw, "<>") && rec->validating) { if (selabel_validate(rec, &spec->lr) < 0) { selinux_log(SELINUX_ERROR, "%s: context %s is invalid\n", path, spec->lr.ctx_raw); goto out; } } /* Process regex string */ rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0 || !entry_len) { rc = -1; goto out; } spec->regex_str = (char *)mmap_area->next_addr; rc = next_entry(NULL, mmap_area, entry_len); if (rc < 0) goto out; if (spec->regex_str[entry_len - 1] != '\0') { rc = -1; goto out; } /* Process mode */ if (version >= SELINUX_COMPILED_FCONTEXT_MODE) rc = next_entry(&mode, mmap_area, sizeof(uint32_t)); else rc = next_entry(&mode, mmap_area, sizeof(mode_t)); if (rc < 0) goto out; spec->mode = mode; /* map the stem id from the mmap file to the data->stem_arr */ rc = next_entry(&stem_id, mmap_area, sizeof(int32_t)); if (rc < 0) goto out; if (stem_id < 0 || stem_id >= (int32_t)stem_map_len) spec->stem_id = -1; else spec->stem_id = stem_map[stem_id]; /* retrieve the hasMetaChars bit */ rc = next_entry(&meta_chars, mmap_area, sizeof(uint32_t)); if (rc < 0) goto out; spec->hasMetaChars = meta_chars; /* and prefix length for use by selabel_lookup_best_match */ if (version >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN) { rc = next_entry(&prefix_len, mmap_area, sizeof(uint32_t)); if (rc < 0) goto out; spec->prefix_len = prefix_len; } rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches, &spec->regex_compiled); if (rc < 0) goto out; __pthread_mutex_init(&spec->regex_lock, NULL); data->nspec++; } rc = 0; out: free(stem_map); return rc; } struct file_details { const char *suffix; struct stat sb; }; static char *rolling_append(char *current, const char *suffix, size_t max) { size_t size; size_t suffix_size; size_t current_size; if (!suffix) return current; current_size = strlen(current); suffix_size = strlen(suffix); size = current_size + suffix_size; if (size < current_size || size < suffix_size) return NULL; /* ensure space for the '.' and the '\0' characters. */ if (size >= (SIZE_MAX - 2)) return NULL; size += 2; if (size > max) return NULL; /* Append any given suffix */ char *to = current + current_size; *to++ = '.'; strcpy(to, suffix); return current; } static bool fcontext_is_binary(FILE *fp) { uint32_t magic; size_t len = fread(&magic, sizeof(magic), 1, fp); rewind(fp); return (len && (magic == SELINUX_MAGIC_COMPILED_FCONTEXT)); } #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static FILE *open_file(const char *path, const char *suffix, char *save_path, size_t len, struct stat *sb, bool open_oldest) { unsigned int i; int rc; char stack_path[len]; struct file_details *found = NULL; /* * Rolling append of suffix. Try to open with path.suffix then the * next as path.suffix.suffix and so forth. */ struct file_details fdetails[2] = { { .suffix = suffix }, { .suffix = "bin" } }; rc = snprintf(stack_path, sizeof(stack_path), "%s", path); if (rc >= (int) sizeof(stack_path)) { errno = ENAMETOOLONG; return NULL; } for (i = 0; i < ARRAY_SIZE(fdetails); i++) { /* This handles the case if suffix is null */ path = rolling_append(stack_path, fdetails[i].suffix, sizeof(stack_path)); if (!path) return NULL; rc = stat(path, &fdetails[i].sb); if (rc) continue; /* first file thing found, just take it */ if (!found) { strcpy(save_path, path); found = &fdetails[i]; continue; } /* * Keep picking the newest file found. Where "newest" * includes equality. This provides a precedence on * secondary suffixes even when the timestamp is the * same. Ie choose file_contexts.bin over file_contexts * even if the time stamp is the same. Invert this logic * on open_oldest set to true. The idea is that if the * newest file failed to process, we can attempt to * process the oldest. The logic here is subtle and depends * on the array ordering in fdetails for the case when time * stamps are the same. */ if (open_oldest ^ (fdetails[i].sb.st_mtime >= found->sb.st_mtime)) { found = &fdetails[i]; strcpy(save_path, path); } } if (!found) { errno = ENOENT; return NULL; } memcpy(sb, &found->sb, sizeof(*sb)); return fopen(save_path, "re"); } static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char *prefix, struct selabel_digest *digest) { int rc; unsigned int i; struct stat sb; FILE *fp = NULL; char found_path[PATH_MAX]; /* * On the first pass open the newest modified file. If it fails to * process, then the second pass shall open the oldest file. If both * passes fail, then it's a fatal error. */ for (i = 0; i < 2; i++) { fp = open_file(path, suffix, found_path, sizeof(found_path), &sb, i > 0); if (fp == NULL) return -1; rc = fcontext_is_binary(fp) ? load_mmap(fp, sb.st_size, rec, found_path) : process_text_file(fp, prefix, rec, found_path); if (!rc) rc = digest_add_specfile(digest, fp, NULL, sb.st_size, found_path); fclose(fp); if (!rc) return 0; } return -1; } static void selabel_subs_fini(struct selabel_sub *ptr) { struct selabel_sub *next; while (ptr) { next = ptr->next; free(ptr->src); free(ptr->dst); free(ptr); ptr = next; } } static char *selabel_sub(struct selabel_sub *ptr, const char *src) { char *dst = NULL; int len; while (ptr) { if (strncmp(src, ptr->src, ptr->slen) == 0 ) { if (src[ptr->slen] == '/' || src[ptr->slen] == 0) { if ((src[ptr->slen] == '/') && (strcmp(ptr->dst, "/") == 0)) len = ptr->slen + 1; else len = ptr->slen; if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0) return NULL; return dst; } } ptr = ptr->next; } return NULL; } #if !defined(BUILD_HOST) && !defined(ANDROID) static int selabel_subs_init(const char *path, struct selabel_digest *digest, struct selabel_sub **out_subs) { char buf[1024]; FILE *cfg = fopen(path, "re"); struct selabel_sub *list = NULL, *sub = NULL; struct stat sb; int status = -1; *out_subs = NULL; if (!cfg) { /* If the file does not exist, it is not fatal */ return (errno == ENOENT) ? 0 : -1; } if (fstat(fileno(cfg), &sb) < 0) goto out; while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) { char *ptr = NULL; char *src = buf; char *dst = NULL; while (*src && isspace(*src)) src++; if (src[0] == '#') continue; ptr = src; while (*ptr && ! isspace(*ptr)) ptr++; *ptr++ = '\0'; if (! *src) continue; dst = ptr; while (*dst && isspace(*dst)) dst++; ptr=dst; while (*ptr && ! isspace(*ptr)) ptr++; *ptr='\0'; if (! *dst) continue; sub = malloc(sizeof(*sub)); if (! sub) goto err; memset(sub, 0, sizeof(*sub)); sub->src=strdup(src); if (! sub->src) goto err; sub->dst=strdup(dst); if (! sub->dst) goto err; sub->slen = strlen(src); sub->next = list; list = sub; sub = NULL; } if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0) goto err; *out_subs = list; status = 0; out: fclose(cfg); return status; err: if (sub) free(sub->src); free(sub); while (list) { sub = list->next; free(list->src); free(list->dst); free(list); list = sub; } goto out; } #endif static char *selabel_sub_key(struct saved_data *data, const char *key) { char *ptr = NULL; char *dptr = NULL; ptr = selabel_sub(data->subs, key); if (ptr) { dptr = selabel_sub(data->dist_subs, ptr); if (dptr) { free(ptr); ptr = dptr; } } else { ptr = selabel_sub(data->dist_subs, key); } if (ptr) return ptr; return NULL; } static void closef(struct selabel_handle *rec); static int init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned n) { struct saved_data *data = (struct saved_data *)rec->data; size_t num_paths = 0; char **path = NULL; const char *prefix = NULL; int status = -1; size_t i; bool baseonly = false; bool path_provided; /* Process arguments */ i = n; while (i--) switch(opts[i].type) { case SELABEL_OPT_PATH: num_paths++; break; case SELABEL_OPT_SUBSET: prefix = opts[i].value; break; case SELABEL_OPT_BASEONLY: baseonly = !!opts[i].value; break; } if (!num_paths) { num_paths = 1; path_provided = false; } else { path_provided = true; } path = calloc(num_paths, sizeof(*path)); if (path == NULL) { goto finish; } rec->spec_files = path; rec->spec_files_len = num_paths; if (path_provided) { for (i = 0; i < n; i++) { switch(opts[i].type) { case SELABEL_OPT_PATH: *path = strdup(opts[i].value); if (*path == NULL) goto finish; path++; break; default: break; } } } #if !defined(BUILD_HOST) && !defined(ANDROID) char subs_file[PATH_MAX + 1]; /* Process local and distribution substitution files */ if (!path_provided) { status = selabel_subs_init( selinux_file_context_subs_dist_path(), rec->digest, &data->dist_subs); if (status) goto finish; status = selabel_subs_init(selinux_file_context_subs_path(), rec->digest, &data->subs); if (status) goto finish; rec->spec_files[0] = strdup(selinux_file_context_path()); if (rec->spec_files[0] == NULL) goto finish; } else { for (i = 0; i < num_paths; i++) { snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", rec->spec_files[i]); status = selabel_subs_init(subs_file, rec->digest, &data->dist_subs); if (status) goto finish; snprintf(subs_file, sizeof(subs_file), "%s.subs", rec->spec_files[i]); status = selabel_subs_init(subs_file, rec->digest, &data->subs); if (status) goto finish; } } #else if (!path_provided) { selinux_log(SELINUX_ERROR, "No path given to file labeling backend\n"); goto finish; } #endif /* * Do detailed validation of the input and fill the spec array */ for (i = 0; i < num_paths; i++) { status = process_file(rec->spec_files[i], NULL, rec, prefix, rec->digest); if (status) goto finish; if (rec->validating) { status = nodups_specs(data, rec->spec_files[i]); if (status) goto finish; } } if (!baseonly) { status = process_file(rec->spec_files[0], "homedirs", rec, prefix, rec->digest); if (status && errno != ENOENT) goto finish; status = process_file(rec->spec_files[0], "local", rec, prefix, rec->digest); if (status && errno != ENOENT) goto finish; } digest_gen_hash(rec->digest); status = sort_specs(data); finish: if (status) closef(rec); return status; } /* * Backend interface routines */ static void closef(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; struct mmap_area *area, *last_area; struct spec *spec; struct stem *stem; unsigned int i; if (!data) return; /* make sure successive ->func_close() calls are harmless */ rec->data = NULL; selabel_subs_fini(data->subs); selabel_subs_fini(data->dist_subs); for (i = 0; i < data->nspec; i++) { spec = &data->spec_arr[i]; free(spec->lr.ctx_trans); free(spec->lr.ctx_raw); regex_data_free(spec->regex); __pthread_mutex_destroy(&spec->regex_lock); if (spec->from_mmap) continue; free(spec->regex_str); free(spec->type_str); } for (i = 0; i < (unsigned int)data->num_stems; i++) { stem = &data->stem_arr[i]; if (stem->from_mmap) continue; free(stem->buf); } if (data->spec_arr) free(data->spec_arr); if (data->stem_arr) free(data->stem_arr); area = data->mmap_areas; while (area) { munmap(area->addr, area->len); last_area = area; area = area->next; free(last_area); } free(data); } // Finds all the matches of |key| in the given context. Returns the result in // the allocated array and updates the match count. If match_count is NULL, // stops early once the 1st match is found. static const struct spec **lookup_all(struct selabel_handle *rec, const char *key, int type, bool partial, size_t *match_count) { struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec_arr = data->spec_arr; int i, rc, file_stem; mode_t mode = (mode_t)type; char *clean_key = NULL; const char *prev_slash, *next_slash; unsigned int sofar = 0; char *sub = NULL; const struct spec **result = NULL; if (match_count) { *match_count = 0; result = calloc(data->nspec, sizeof(struct spec*)); } else { result = calloc(1, sizeof(struct spec*)); } if (!result) { selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); goto finish; } if (!data->nspec) { errno = ENOENT; goto finish; } /* Remove duplicate slashes */ if ((next_slash = strstr(key, "//"))) { clean_key = (char *) malloc(strlen(key) + 1); if (!clean_key) goto finish; prev_slash = key; while (next_slash) { memcpy(clean_key + sofar, prev_slash, next_slash - prev_slash); sofar += next_slash - prev_slash; prev_slash = next_slash + 1; next_slash = strstr(prev_slash, "//"); } strcpy(clean_key + sofar, prev_slash); key = clean_key; } sub = selabel_sub_key(data, key); if (sub) key = sub; file_stem = find_stem_from_file(data, key); mode &= S_IFMT; /* * Check for matching specifications in reverse order, so that * the last matching specification is used. */ for (i = data->nspec - 1; i >= 0; i--) { struct spec *spec = &spec_arr[i]; /* if the spec in question matches no stem or has the same * stem as the file AND if the spec in question has no mode * specified or if the mode matches the file mode then we do * a regex check */ bool stem_matches = spec->stem_id == -1 || spec->stem_id == file_stem; // Don't check the stem if we want to find partial matches. // Otherwise the case "/abc/efg/(/.*)?" will be considered //a miss for "/abc". if ((partial || stem_matches) && (!mode || !spec->mode || mode == spec->mode)) { if (compile_regex(spec, NULL) < 0) goto finish; rc = regex_match(spec->regex, key, partial); if (rc == REGEX_MATCH || (partial && rc == REGEX_MATCH_PARTIAL)) { if (rc == REGEX_MATCH) { spec->matches++; } if (strcmp(spec_arr[i].lr.ctx_raw, "<>") == 0) { errno = ENOENT; goto finish; } if (match_count) { result[*match_count] = spec; *match_count += 1; // Continue to find all the matches. continue; } result[0] = spec; break; } if (rc == REGEX_NO_MATCH) continue; errno = ENOENT; /* else it's an error */ goto finish; } } finish: free(clean_key); free(sub); if (result && !result[0]) { free(result); result = NULL; } return result; } static struct spec *lookup_common(struct selabel_handle *rec, const char *key, int type, bool partial) { const struct spec **matches = lookup_all(rec, key, type, partial, NULL); if (!matches) { return NULL; } struct spec *result = (struct spec*)matches[0]; free(matches); return result; } static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key, uint8_t *digest) { assert(digest); size_t total_matches; const struct spec **matches = lookup_all(rec, key, 0, true, &total_matches); if (!matches) { return false; } Sha1Context context; Sha1Initialise(&context); size_t i; for (i = 0; i < total_matches; i++) { char* regex_str = matches[i]->regex_str; uint32_t mode = matches[i]->mode; char* ctx_raw = matches[i]->lr.ctx_raw; Sha1Update(&context, regex_str, strlen(regex_str) + 1); Sha1Update(&context, &mode, sizeof(uint32_t)); Sha1Update(&context, ctx_raw, strlen(ctx_raw) + 1); } SHA1_HASH sha1_hash; Sha1Finalise(&context, &sha1_hash); memcpy(digest, sha1_hash.bytes, SHA1_HASH_SIZE); free(matches); return true; } static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, const char *key, int type) { struct spec *spec; spec = lookup_common(rec, key, type, false); if (spec) return &spec->lr; return NULL; } static bool partial_match(struct selabel_handle *rec, const char *key) { return lookup_common(rec, key, 0, true) ? true : false; } static struct selabel_lookup_rec *lookup_best_match(struct selabel_handle *rec, const char *key, const char **aliases, int type) { size_t n, i; int best = -1; struct spec **specs; size_t prefix_len = 0; struct selabel_lookup_rec *lr = NULL; if (!aliases || !aliases[0]) return lookup(rec, key, type); for (n = 0; aliases[n]; n++) ; specs = calloc(n+1, sizeof(struct spec *)); if (!specs) return NULL; specs[0] = lookup_common(rec, key, type, false); if (specs[0]) { if (!specs[0]->hasMetaChars) { /* exact match on key */ lr = &specs[0]->lr; goto out; } best = 0; prefix_len = specs[0]->prefix_len; } for (i = 1; i <= n; i++) { specs[i] = lookup_common(rec, aliases[i-1], type, false); if (specs[i]) { if (!specs[i]->hasMetaChars) { /* exact match on alias */ lr = &specs[i]->lr; goto out; } if (specs[i]->prefix_len > prefix_len) { best = i; prefix_len = specs[i]->prefix_len; } } } if (best >= 0) { /* longest fixed prefix match on key or alias */ lr = &specs[best]->lr; } else { errno = ENOENT; } out: free(specs); return lr; } static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, const char *reason, int i, int j) { selinux_log(SELINUX_INFO, "selabel_cmp: mismatched %s on entry %d: (%s, %x, %s) vs entry %d: (%s, %x, %s)\n", reason, i, spec1->regex_str, spec1->mode, spec1->lr.ctx_raw, j, spec2->regex_str, spec2->mode, spec2->lr.ctx_raw); return SELABEL_INCOMPARABLE; } static enum selabel_cmp_result cmp(struct selabel_handle *h1, struct selabel_handle *h2) { struct saved_data *data1 = (struct saved_data *)h1->data; struct saved_data *data2 = (struct saved_data *)h2->data; unsigned int i, nspec1 = data1->nspec, j, nspec2 = data2->nspec; struct spec *spec_arr1 = data1->spec_arr, *spec_arr2 = data2->spec_arr; struct stem *stem_arr1 = data1->stem_arr, *stem_arr2 = data2->stem_arr; bool skipped1 = false, skipped2 = false; i = 0; j = 0; while (i < nspec1 && j < nspec2) { struct spec *spec1 = &spec_arr1[i]; struct spec *spec2 = &spec_arr2[j]; /* * Because sort_specs() moves exact pathnames to the * end, we might need to skip over additional regex * entries that only exist in one of the configurations. */ if (!spec1->hasMetaChars && spec2->hasMetaChars) { j++; skipped2 = true; continue; } if (spec1->hasMetaChars && !spec2->hasMetaChars) { i++; skipped1 = true; continue; } if (spec1->regex && spec2->regex) { if (regex_cmp(spec1->regex, spec2->regex) == SELABEL_INCOMPARABLE){ return incomp(spec1, spec2, "regex", i, j); } } else { if (strcmp(spec1->regex_str, spec2->regex_str)) return incomp(spec1, spec2, "regex_str", i, j); } if (spec1->mode != spec2->mode) return incomp(spec1, spec2, "mode", i, j); if (spec1->stem_id == -1 && spec2->stem_id != -1) return incomp(spec1, spec2, "stem_id", i, j); if (spec2->stem_id == -1 && spec1->stem_id != -1) return incomp(spec1, spec2, "stem_id", i, j); if (spec1->stem_id != -1 && spec2->stem_id != -1) { struct stem *stem1 = &stem_arr1[spec1->stem_id]; struct stem *stem2 = &stem_arr2[spec2->stem_id]; if (stem1->len != stem2->len || strncmp(stem1->buf, stem2->buf, stem1->len)) return incomp(spec1, spec2, "stem", i, j); } if (strcmp(spec1->lr.ctx_raw, spec2->lr.ctx_raw)) return incomp(spec1, spec2, "ctx_raw", i, j); i++; j++; } if ((skipped1 || i < nspec1) && !skipped2) return SELABEL_SUPERSET; if ((skipped2 || j < nspec2) && !skipped1) return SELABEL_SUBSET; if (skipped1 && skipped2) return SELABEL_INCOMPARABLE; return SELABEL_EQUAL; } static void stats(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; unsigned int i, nspec = data->nspec; struct spec *spec_arr = data->spec_arr; for (i = 0; i < nspec; i++) { if (spec_arr[i].matches == 0) { if (spec_arr[i].type_str) { COMPAT_LOG(SELINUX_WARNING, "Warning! No matches for (%s, %s, %s)\n", spec_arr[i].regex_str, spec_arr[i].type_str, spec_arr[i].lr.ctx_raw); } else { COMPAT_LOG(SELINUX_WARNING, "Warning! No matches for (%s, %s)\n", spec_arr[i].regex_str, spec_arr[i].lr.ctx_raw); } } } } int selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { struct saved_data *data; data = (struct saved_data *)malloc(sizeof(*data)); if (!data) return -1; memset(data, 0, sizeof(*data)); rec->data = data; rec->func_close = &closef; rec->func_stats = &stats; rec->func_lookup = &lookup; rec->func_partial_match = &partial_match; rec->func_hash_all_partial_matches = &hash_all_partial_matches; rec->func_lookup_best_match = &lookup_best_match; rec->func_cmp = &cmp; return init(rec, opts, nopts); } libselinux/src/label_file.h0100644 0000000 0000000 00000030422 13756670063 015017 0ustar000000000 0000000 #ifndef _SELABEL_FILE_H_ #define _SELABEL_FILE_H_ #include #include #include #include /* * regex.h/c were introduced to hold all dependencies on the regular * expression back-end when we started supporting PCRE2. regex.h defines a * minimal interface required by libselinux, so that the remaining code * can be agnostic about the underlying implementation. */ #include "regex.h" #include "callbacks.h" #include "label_internal.h" #include "selinux_internal.h" #define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a /* Version specific changes */ #define SELINUX_COMPILED_FCONTEXT_NOPCRE_VERS 1 #define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2 #define SELINUX_COMPILED_FCONTEXT_MODE 3 #define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4 #define SELINUX_COMPILED_FCONTEXT_REGEX_ARCH 5 #define SELINUX_COMPILED_FCONTEXT_MAX_VERS \ SELINUX_COMPILED_FCONTEXT_REGEX_ARCH struct selabel_sub { char *src; int slen; char *dst; struct selabel_sub *next; }; /* A file security context specification. */ struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ char *regex_str; /* regular expession string for diagnostics */ char *type_str; /* type string for diagnostic messages */ struct regex_data * regex; /* backend dependent regular expression data */ bool regex_compiled; /* bool to indicate if the regex is compiled */ pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */ mode_t mode; /* mode format value */ int matches; /* number of matching pathnames */ int stem_id; /* indicates which stem-compression item */ char hasMetaChars; /* regular expression has meta-chars */ char from_mmap; /* this spec is from an mmap of the data */ size_t prefix_len; /* length of fixed path prefix */ }; /* A regular expression stem */ struct stem { char *buf; int len; char from_mmap; }; /* Where we map the file in during selabel_open() */ struct mmap_area { void *addr; /* Start addr + len used to release memory at close */ size_t len; void *next_addr; /* Incremented by next_entry() */ size_t next_len; /* Decremented by next_entry() */ struct mmap_area *next; }; /* Our stored configuration */ struct saved_data { /* * The array of specifications, initially in the same order as in * the specification file. Sorting occurs based on hasMetaChars. */ struct spec *spec_arr; unsigned int nspec; unsigned int alloc_specs; /* * The array of regular expression stems. */ struct stem *stem_arr; int num_stems; int alloc_stems; struct mmap_area *mmap_areas; /* substitution support */ struct selabel_sub *dist_subs; struct selabel_sub *subs; }; static inline mode_t string_to_mode(char *mode) { size_t len; if (!mode) return 0; len = strlen(mode); if (mode[0] != '-' || len != 2) return -1; switch (mode[1]) { case 'b': return S_IFBLK; case 'c': return S_IFCHR; case 'd': return S_IFDIR; case 'p': return S_IFIFO; case 'l': return S_IFLNK; case 's': return S_IFSOCK; case '-': return S_IFREG; default: return -1; } /* impossible to get here */ return 0; } static inline int grow_specs(struct saved_data *data) { struct spec *specs; size_t new_specs, total_specs; if (data->nspec < data->alloc_specs) return 0; new_specs = data->nspec + 16; total_specs = data->nspec + new_specs; specs = realloc(data->spec_arr, total_specs * sizeof(*specs)); if (!specs) { perror("realloc"); return -1; } /* blank the new entries */ memset(&specs[data->nspec], 0, new_specs * sizeof(*specs)); data->spec_arr = specs; data->alloc_specs = total_specs; return 0; } /* Determine if the regular expression specification has any meta characters. */ static inline void spec_hasMetaChars(struct spec *spec) { char *c; int len; char *end; c = spec->regex_str; len = strlen(spec->regex_str); end = c + len; spec->hasMetaChars = 0; spec->prefix_len = len; /* Look at each character in the RE specification string for a * meta character. Return when any meta character reached. */ while (c < end) { switch (*c) { case '.': case '^': case '$': case '?': case '*': case '+': case '|': case '[': case '(': case '{': spec->hasMetaChars = 1; spec->prefix_len = c - spec->regex_str; return; case '\\': /* skip the next character */ c++; break; default: break; } c++; } } /* Move exact pathname specifications to the end. */ static inline int sort_specs(struct saved_data *data) { struct spec *spec_copy; struct spec spec; unsigned int i; int front, back; size_t len = sizeof(*spec_copy); spec_copy = malloc(len * data->nspec); if (!spec_copy) return -1; /* first move the exact pathnames to the back */ front = 0; back = data->nspec - 1; for (i = 0; i < data->nspec; i++) { if (data->spec_arr[i].hasMetaChars) memcpy(&spec_copy[front++], &data->spec_arr[i], len); else memcpy(&spec_copy[back--], &data->spec_arr[i], len); } /* * now the exact pathnames are at the end, but they are in the reverse * order. Since 'front' is now the first of the 'exact' we can run * that part of the array switching the front and back element. */ back = data->nspec - 1; while (front < back) { /* save the front */ memcpy(&spec, &spec_copy[front], len); /* move the back to the front */ memcpy(&spec_copy[front], &spec_copy[back], len); /* put the old front in the back */ memcpy(&spec_copy[back], &spec, len); front++; back--; } free(data->spec_arr); data->spec_arr = spec_copy; return 0; } /* Return the length of the text that can be considered the stem, returns 0 * if there is no identifiable stem */ static inline int get_stem_from_spec(const char *const buf) { const char *tmp = strchr(buf + 1, '/'); const char *ind; if (!tmp) return 0; for (ind = buf; ind < tmp; ind++) { if (strchr(".^$?*+|[({", (int)*ind)) return 0; } return tmp - buf; } /* * return the stemid given a string and a length */ static inline int find_stem(struct saved_data *data, const char *buf, int stem_len) { int i; for (i = 0; i < data->num_stems; i++) { if (stem_len == data->stem_arr[i].len && !strncmp(buf, data->stem_arr[i].buf, stem_len)) return i; } return -1; } /* returns the index of the new stored object */ static inline int store_stem(struct saved_data *data, char *buf, int stem_len) { int num = data->num_stems; if (data->alloc_stems == num) { struct stem *tmp_arr; int alloc_stems = data->alloc_stems * 2 + 16; tmp_arr = realloc(data->stem_arr, sizeof(*tmp_arr) * alloc_stems); if (!tmp_arr) { free(buf); return -1; } data->alloc_stems = alloc_stems; data->stem_arr = tmp_arr; } data->stem_arr[num].len = stem_len; data->stem_arr[num].buf = buf; data->stem_arr[num].from_mmap = 0; data->num_stems++; return num; } /* find the stem of a file spec, returns the index into stem_arr for a new * or existing stem, (or -1 if there is no possible stem - IE for a file in * the root directory or a regex that is too complex for us). */ static inline int find_stem_from_spec(struct saved_data *data, const char *buf) { int stem_len = get_stem_from_spec(buf); int stemid; char *stem; if (!stem_len) return -1; stemid = find_stem(data, buf, stem_len); if (stemid >= 0) return stemid; /* not found, allocate a new one */ stem = strndup(buf, stem_len); if (!stem) return -1; return store_stem(data, stem, stem_len); } /* This will always check for buffer over-runs and either read the next entry * if buf != NULL or skip over the entry (as these areas are mapped in the * current buffer). */ static inline int next_entry(void *buf, struct mmap_area *fp, size_t bytes) { if (bytes > fp->next_len) return -1; if (buf) memcpy(buf, fp->next_addr, bytes); fp->next_addr = (char *)fp->next_addr + bytes; fp->next_len -= bytes; return 0; } static inline int compile_regex(struct spec *spec, const char **errbuf) { char *reg_buf, *anchored_regex, *cp; struct regex_error_data error_data; static char regex_error_format_buffer[256]; size_t len; int rc; bool regex_compiled; /* We really want pthread_once() here, but since its * init_routine does not take a parameter, it's not possible * to use, so we generate the same effect with atomics and a * mutex */ #ifdef __ATOMIC_RELAXED regex_compiled = __atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE); #else /* GCC <4.7 */ __sync_synchronize(); regex_compiled = spec->regex_compiled; #endif if (regex_compiled) { return 0; /* already done */ } __pthread_mutex_lock(&spec->regex_lock); /* Check if another thread compiled the regex while we waited * on the mutex */ #ifdef __ATOMIC_RELAXED regex_compiled = __atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE); #else /* GCC <4.7 */ __sync_synchronize(); regex_compiled = spec->regex_compiled; #endif if (regex_compiled) { __pthread_mutex_unlock(&spec->regex_lock); return 0; } reg_buf = spec->regex_str; /* Anchor the regular expression. */ len = strlen(reg_buf); cp = anchored_regex = malloc(len + 3); if (!anchored_regex) { if (errbuf) *errbuf = "out of memory"; __pthread_mutex_unlock(&spec->regex_lock); return -1; } /* Create ^...$ regexp. */ *cp++ = '^'; memcpy(cp, reg_buf, len); cp += len; *cp++ = '$'; *cp = '\0'; /* Compile the regular expression. */ rc = regex_prepare_data(&spec->regex, anchored_regex, &error_data); free(anchored_regex); if (rc < 0) { if (errbuf) { regex_format_error(&error_data, regex_error_format_buffer, sizeof(regex_error_format_buffer)); *errbuf = ®ex_error_format_buffer[0]; } __pthread_mutex_unlock(&spec->regex_lock); return -1; } /* Done. */ #ifdef __ATOMIC_RELAXED __atomic_store_n(&spec->regex_compiled, true, __ATOMIC_RELEASE); #else /* GCC <4.7 */ spec->regex_compiled = true; __sync_synchronize(); #endif __pthread_mutex_unlock(&spec->regex_lock); return 0; } /* This service is used by label_file.c process_file() and * utils/sefcontext_compile.c */ static inline int process_line(struct selabel_handle *rec, const char *path, const char *prefix, char *line_buf, unsigned lineno) { int items, len, rc; char *regex = NULL, *type = NULL, *context = NULL; struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec_arr; unsigned int nspec = data->nspec; const char *errbuf = NULL; items = read_spec_entries(line_buf, &errbuf, 3, ®ex, &type, &context); if (items < 0) { rc = errno; selinux_log(SELINUX_ERROR, "%s: line %u error due to: %s\n", path, lineno, errbuf ?: strerror(errno)); errno = rc; return -1; } if (items == 0) return items; if (items < 2) { COMPAT_LOG(SELINUX_ERROR, "%s: line %u is missing fields\n", path, lineno); if (items == 1) free(regex); errno = EINVAL; return -1; } else if (items == 2) { /* The type field is optional. */ context = type; type = 0; } len = get_stem_from_spec(regex); if (len && prefix && strncmp(prefix, regex, len)) { /* Stem of regex does not match requested prefix, discard. */ free(regex); free(type); free(context); return 0; } rc = grow_specs(data); if (rc) return rc; spec_arr = data->spec_arr; /* process and store the specification in spec. */ spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); spec_arr[nspec].regex_str = regex; __pthread_mutex_init(&spec_arr[nspec].regex_lock, NULL); spec_arr[nspec].regex_compiled = false; spec_arr[nspec].type_str = type; spec_arr[nspec].mode = 0; spec_arr[nspec].lr.ctx_raw = context; spec_arr[nspec].lr.lineno = lineno; /* * bump data->nspecs to cause closef() to cover it in its free * but do not bump nspec since it's used below. */ data->nspec++; if (rec->validating && compile_regex(&spec_arr[nspec], &errbuf)) { COMPAT_LOG(SELINUX_ERROR, "%s: line %u has invalid regex %s: %s\n", path, lineno, regex, errbuf); errno = EINVAL; return -1; } if (type) { mode_t mode = string_to_mode(type); if (mode == (mode_t)-1) { COMPAT_LOG(SELINUX_ERROR, "%s: line %u has invalid file type %s\n", path, lineno, type); errno = EINVAL; return -1; } spec_arr[nspec].mode = mode; } /* Determine if specification has * any meta characters in the RE */ spec_hasMetaChars(&spec_arr[nspec]); if (strcmp(context, "<>") && rec->validating) return compat_validate(rec, &spec_arr[nspec].lr, path, lineno); return 0; } #endif /* _SELABEL_FILE_H_ */ libselinux/src/label_internal.h0100644 0000000 0000000 00000010307 13756670063 015714 0ustar000000000 0000000 /* * This file describes the internal interface used by the labeler * for calling the user-supplied memory allocation, validation, * and locking routine. * * Author : Eamon Walsh */ #ifndef _SELABEL_INTERNAL_H_ #define _SELABEL_INTERNAL_H_ #include #include #include #include #include #include "dso.h" #include "sha1.h" #if defined(ANDROID) || defined(__APPLE__) // Android and Mac do not have fgets_unlocked() #define fgets_unlocked(buf, size, fp) fgets(buf, size, fp) #endif /* * Installed backends */ int selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; int selabel_media_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; int selabel_x_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; int selabel_db_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; int selabel_property_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; int selabel_service_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) hidden; /* * Labeling internal structures */ /* * Calculate an SHA1 hash of all the files used to build the specs. * The hash value is held in rec->digest if SELABEL_OPT_DIGEST set. To * calculate the hash the hashbuf will hold a concatenation of all the files * used. This is released once the value has been calculated. */ #define DIGEST_SPECFILE_SIZE SHA1_HASH_SIZE #define DIGEST_FILES_MAX 8 struct selabel_digest { unsigned char *digest; /* SHA1 digest of specfiles */ unsigned char *hashbuf; /* buffer to hold specfiles */ size_t hashbuf_size; /* buffer size */ size_t specfile_cnt; /* how many specfiles processed */ char **specfile_list; /* and their names */ }; extern int digest_add_specfile(struct selabel_digest *digest, FILE *fp, char *from_addr, size_t buf_len, const char *path); extern void digest_gen_hash(struct selabel_digest *digest); struct selabel_lookup_rec { char * ctx_raw; char * ctx_trans; int validated; unsigned lineno; }; struct selabel_handle { /* arguments that were passed to selabel_open */ unsigned int backend; int validating; /* labeling operations */ struct selabel_lookup_rec *(*func_lookup) (struct selabel_handle *h, const char *key, int type); void (*func_close) (struct selabel_handle *h); void (*func_stats) (struct selabel_handle *h); bool (*func_partial_match) (struct selabel_handle *h, const char *key); bool (*func_hash_all_partial_matches) (struct selabel_handle *h, const char *key, uint8_t *digest); struct selabel_lookup_rec *(*func_lookup_best_match) (struct selabel_handle *h, const char *key, const char **aliases, int type); enum selabel_cmp_result (*func_cmp)(struct selabel_handle *h1, struct selabel_handle *h2); /* supports backend-specific state information */ void *data; /* * The main spec file(s) used. Note for file contexts the local and/or * homedirs could also have been used to resolve a context. */ size_t spec_files_len; char **spec_files; /* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */ struct selabel_digest *digest; }; /* * Validation function */ extern int selabel_validate(struct selabel_handle *rec, struct selabel_lookup_rec *contexts) hidden; /* * Compatibility support */ extern int myprintf_compat; extern void __attribute__ ((format(printf, 1, 2))) (*myprintf) (const char *fmt, ...) hidden; #define COMPAT_LOG(type, fmt...) if (myprintf_compat) \ myprintf(fmt); \ else \ selinux_log(type, fmt); extern int compat_validate(struct selabel_handle *rec, struct selabel_lookup_rec *contexts, const char *path, unsigned lineno) hidden; /* * The read_spec_entries function may be used to * replace sscanf to read entries from spec files. */ extern int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...); #endif /* _SELABEL_INTERNAL_H_ */ libselinux/src/label_media.c0100644 0000000 0000000 00000011443 13756670063 015154 0ustar000000000 0000000 /* * Media contexts backend for labeling system * * Author : Eamon Walsh */ #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" /* * Internals */ /* A context specification. */ typedef struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ char *key; /* key string */ int matches; /* number of matches made during operation */ } spec_t; struct saved_data { unsigned int nspec; spec_t *spec_arr; }; static int process_line(const char *path, char *line_buf, int pass, unsigned lineno, struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; int items; char *buf_p; char *key, *context; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) return 0; items = sscanf(line_buf, "%ms %ms ", &key, &context); if (items < 2) { selinux_log(SELINUX_WARNING, "%s: line %u is missing fields, skipping\n", path, lineno); if (items == 1) free(key); return 0; } if (pass == 1) { data->spec_arr[data->nspec].key = key; data->spec_arr[data->nspec].lr.ctx_raw = context; } data->nspec++; if (pass == 0) { free(key); free(context); } return 0; } static int init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned n) { FILE *fp; struct saved_data *data = (struct saved_data *)rec->data; const char *path = NULL; char *line_buf = NULL; size_t line_len = 0; int status = -1; unsigned int lineno, pass, maxnspec; struct stat sb; /* Process arguments */ while (n--) switch(opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; break; } /* Open the specification file. */ if (!path) path = selinux_media_context_path(); if ((fp = fopen(path, "re")) == NULL) return -1; __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fstat(fileno(fp), &sb) < 0) return -1; if (!S_ISREG(sb.st_mode)) { errno = EINVAL; return -1; } rec->spec_file = strdup(path); /* * Perform two passes over the specification file. * The first pass counts the number of specifications and * performs simple validation of the input. At the end * of the first pass, the spec array is allocated. * The second pass performs detailed validation of the input * and fills in the spec array. */ maxnspec = UINT_MAX / sizeof(spec_t); for (pass = 0; pass < 2; pass++) { lineno = 0; data->nspec = 0; while (getline(&line_buf, &line_len, fp) > 0 && data->nspec < maxnspec) { if (process_line(path, line_buf, pass, ++lineno, rec)) goto finish; } lineno = 0; if (pass == 0) { if (data->nspec == 0) { status = 0; goto finish; } data->spec_arr = malloc(sizeof(spec_t)*data->nspec); if (data->spec_arr == NULL) goto finish; memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); maxnspec = data->nspec; rewind(fp); } } free(line_buf); status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path); if (status) goto finish; digest_gen_hash(rec->digest); finish: fclose(fp); return status; } /* * Backend interface routines */ static void close(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec, *spec_arr = data->spec_arr; unsigned int i; for (i = 0; i < data->nspec; i++) { spec = &spec_arr[i]; free(spec->key); free(spec->lr.ctx_raw); free(spec->lr.ctx_trans); } if (spec_arr) free(spec_arr); free(data); } static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, const char *key, int type __attribute__((unused))) { struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int i; for (i = 0; i < data->nspec; i++) { if (!strncmp(spec_arr[i].key, key, strlen(key) + 1)) break; if (!strncmp(spec_arr[i].key, "*", 2)) break; } if (i >= data->nspec) { /* No matching specification. */ errno = ENOENT; return NULL; } spec_arr[i].matches++; return &spec_arr[i].lr; } static void stats(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; unsigned int i, total = 0; for (i = 0; i < data->nspec; i++) total += data->spec_arr[i].matches; selinux_log(SELINUX_INFO, "%u entries, %u matches made\n", data->nspec, total); } int selabel_media_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { struct saved_data *data; data = (struct saved_data *)malloc(sizeof(*data)); if (!data) return -1; memset(data, 0, sizeof(*data)); rec->data = data; rec->func_close = &close; rec->func_lookup = &lookup; rec->func_stats = &stats; return init(rec, opts, nopts); } libselinux/src/label_support.c0100644 0000000 0000000 00000010756 13756670063 015617 0ustar000000000 0000000 /* * This file contains helper functions for labeling support. * * Author : Richard Haines */ #include #include #include #include #include #include #include #include "label_internal.h" /* * Read an entry from a spec file (e.g. file_contexts) * entry - Buffer to allocate for the entry. * ptr - current location of the line to be processed. * returns - 0 on success and *entry is set to be a null * terminated value. On Error it returns -1 and * errno will be set. * */ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf) { *entry = NULL; char *tmp_buf = NULL; while (isspace(**ptr) && **ptr != '\0') (*ptr)++; tmp_buf = *ptr; *len = 0; while (!isspace(**ptr) && **ptr != '\0') { if (!isascii(**ptr)) { errno = EINVAL; *errbuf = "Non-ASCII characters found"; return -1; } (*ptr)++; (*len)++; } if (*len) { *entry = strndup(tmp_buf, *len); if (!*entry) return -1; } return 0; } /* * line_buf - Buffer containing the spec entries . * errbuf - Double pointer used for passing back specific error messages. * num_args - The number of spec parameter entries to process. * ... - A 'char **spec_entry' for each parameter. * returns - The number of items processed. On error, it returns -1 with errno * set and may set errbuf to a specific error message. * * This function calls read_spec_entry() to do the actual string processing. * As such, can return anything from that function as well. */ int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...) { char **spec_entry, *buf_p; int len, rc, items, entry_len = 0; va_list ap; *errbuf = NULL; len = strlen(line_buf); if (line_buf[len - 1] == '\n') line_buf[len - 1] = '\0'; else /* Handle case if line not \n terminated by bumping * the len for the check below (as the line is NUL * terminated by getline(3)) */ len++; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == '\0') return 0; /* Process the spec file entries */ va_start(ap, num_args); items = 0; while (items < num_args) { spec_entry = va_arg(ap, char **); if (len - 1 == buf_p - line_buf) { va_end(ap); return items; } rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf); if (rc < 0) { va_end(ap); return rc; } if (entry_len) items++; } va_end(ap); return items; } /* Once all the specfiles are in the hash_buf, generate the hash. */ void hidden digest_gen_hash(struct selabel_digest *digest) { Sha1Context context; /* If SELABEL_OPT_DIGEST not set then just return */ if (!digest) return; Sha1Initialise(&context); Sha1Update(&context, digest->hashbuf, digest->hashbuf_size); Sha1Finalise(&context, (SHA1_HASH *)digest->digest); free(digest->hashbuf); digest->hashbuf = NULL; return; } /** * digest_add_specfile - Add a specfile to the hashbuf and if gen_hash true * then generate the hash. * @digest: pointer to the selabel_digest struct * @fp: file pointer for fread(3) or NULL if not. * @from_addr: pointer at start of buffer for memcpy or NULL if not (used for * mmap(3) files). * @buf_len: length of buffer to copy. * @path: pointer to the specfile. * * Return %0 on success, -%1 with @errno set on failure. */ int hidden digest_add_specfile(struct selabel_digest *digest, FILE *fp, char *from_addr, size_t buf_len, const char *path) { unsigned char *tmp_buf; /* If SELABEL_OPT_DIGEST not set then just return */ if (!digest) return 0; if (digest->hashbuf_size + buf_len < digest->hashbuf_size) { errno = EOVERFLOW; return -1; } digest->hashbuf_size += buf_len; tmp_buf = realloc(digest->hashbuf, digest->hashbuf_size); if (!tmp_buf) return -1; digest->hashbuf = tmp_buf; if (fp) { rewind(fp); if (fread(digest->hashbuf + (digest->hashbuf_size - buf_len), 1, buf_len, fp) != buf_len) return -1; rewind(fp); } else if (from_addr) { tmp_buf = memcpy(digest->hashbuf + (digest->hashbuf_size - buf_len), from_addr, buf_len); if (!tmp_buf) return -1; } /* Now add path to list */ digest->specfile_list[digest->specfile_cnt] = strdup(path); if (!digest->specfile_list[digest->specfile_cnt]) return -1; digest->specfile_cnt++; if (digest->specfile_cnt > DIGEST_FILES_MAX) { errno = EOVERFLOW; return -1; } return 0; } libselinux/src/label_x.c0100644 0000000 0000000 00000013302 13756670063 014340 0ustar000000000 0000000 /* * Media contexts backend for X contexts * * Author : Eamon Walsh */ #include #include #include #include #include #include #include #include #include "callbacks.h" #include "label_internal.h" /* * Internals */ /* A context specification. */ typedef struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ char *key; /* key string */ int type; /* type of record (prop, ext, client) */ int matches; /* number of matches made during operation */ } spec_t; struct saved_data { unsigned int nspec; spec_t *spec_arr; }; static int process_line(const char *path, char *line_buf, int pass, unsigned lineno, struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; int items; char *buf_p; char *type, *key, *context; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) return 0; items = sscanf(line_buf, "%ms %ms %ms ", &type, &key, &context); if (items < 3) { selinux_log(SELINUX_WARNING, "%s: line %u is missing fields, skipping\n", path, lineno); if (items > 0) free(type); if (items > 1) free(key); return 0; } if (pass == 1) { /* Convert the type string to a mode format */ if (!strcmp(type, "property")) data->spec_arr[data->nspec].type = SELABEL_X_PROP; else if (!strcmp(type, "extension")) data->spec_arr[data->nspec].type = SELABEL_X_EXT; else if (!strcmp(type, "client")) data->spec_arr[data->nspec].type = SELABEL_X_CLIENT; else if (!strcmp(type, "event")) data->spec_arr[data->nspec].type = SELABEL_X_EVENT; else if (!strcmp(type, "selection")) data->spec_arr[data->nspec].type = SELABEL_X_SELN; else if (!strcmp(type, "poly_property")) data->spec_arr[data->nspec].type = SELABEL_X_POLYPROP; else if (!strcmp(type, "poly_selection")) data->spec_arr[data->nspec].type = SELABEL_X_POLYSELN; else { selinux_log(SELINUX_WARNING, "%s: line %u has invalid object type %s\n", path, lineno, type); return 0; } data->spec_arr[data->nspec].key = key; data->spec_arr[data->nspec].lr.ctx_raw = context; free(type); } data->nspec++; if (pass == 0) { free(type); free(key); free(context); } return 0; } static int init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned n) { FILE *fp; struct saved_data *data = (struct saved_data *)rec->data; const char *path = NULL; char *line_buf = NULL; size_t line_len = 0; int status = -1; unsigned int lineno, pass, maxnspec; struct stat sb; /* Process arguments */ while (n--) switch(opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; break; } /* Open the specification file. */ if (!path) path = selinux_x_context_path(); if ((fp = fopen(path, "re")) == NULL) return -1; __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fstat(fileno(fp), &sb) < 0) return -1; if (!S_ISREG(sb.st_mode)) { errno = EINVAL; return -1; } rec->spec_file = strdup(path); /* * Perform two passes over the specification file. * The first pass counts the number of specifications and * performs simple validation of the input. At the end * of the first pass, the spec array is allocated. * The second pass performs detailed validation of the input * and fills in the spec array. */ maxnspec = UINT_MAX / sizeof(spec_t); for (pass = 0; pass < 2; pass++) { lineno = 0; data->nspec = 0; while (getline(&line_buf, &line_len, fp) > 0 && data->nspec < maxnspec) { if (process_line(path, line_buf, pass, ++lineno, rec)) goto finish; } lineno = 0; if (pass == 0) { if (data->nspec == 0) { status = 0; goto finish; } data->spec_arr = malloc(sizeof(spec_t)*data->nspec); if (data->spec_arr == NULL) goto finish; memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); maxnspec = data->nspec; rewind(fp); } } free(line_buf); status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path); if (status) goto finish; digest_gen_hash(rec->digest); finish: fclose(fp); return status; } /* * Backend interface routines */ static void close(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec, *spec_arr = data->spec_arr; unsigned int i; for (i = 0; i < data->nspec; i++) { spec = &spec_arr[i]; free(spec->key); free(spec->lr.ctx_raw); free(spec->lr.ctx_trans); } if (spec_arr) free(spec_arr); free(data); } static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, const char *key, int type) { struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int i; for (i = 0; i < data->nspec; i++) { if (spec_arr[i].type != type) continue; if (!fnmatch(spec_arr[i].key, key, 0)) break; } if (i >= data->nspec) { /* No matching specification. */ errno = ENOENT; return NULL; } spec_arr[i].matches++; return &spec_arr[i].lr; } static void stats(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; unsigned int i, total = 0; for (i = 0; i < data->nspec; i++) total += data->spec_arr[i].matches; selinux_log(SELINUX_INFO, "%u entries, %u matches made\n", data->nspec, total); } int selabel_x_init(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts) { struct saved_data *data; data = (struct saved_data *)malloc(sizeof(*data)); if (!data) return -1; memset(data, 0, sizeof(*data)); rec->data = data; rec->func_close = &close; rec->func_lookup = &lookup; rec->func_stats = &stats; return init(rec, opts, nopts); } libselinux/src/lgetfilecon.c0100644 0000000 0000000 00000002361 13756670063 015230 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" int lgetfilecon_raw(const char *path, char ** context) { char *buf; ssize_t size; ssize_t ret; size = INITCONTEXTLEN + 1; buf = malloc(size); if (!buf) return -1; memset(buf, 0, size); ret = lgetxattr(path, XATTR_NAME_SELINUX, buf, size - 1); if (ret < 0 && errno == ERANGE) { char *newbuf; size = lgetxattr(path, XATTR_NAME_SELINUX, NULL, 0); if (size < 0) goto out; size++; newbuf = realloc(buf, size); if (!newbuf) goto out; buf = newbuf; memset(buf, 0, size); ret = lgetxattr(path, XATTR_NAME_SELINUX, buf, size - 1); } out: if (ret == 0) { /* Re-map empty attribute values to errors. */ errno = ENOTSUP; ret = -1; } if (ret < 0) free(buf); else *context = buf; return ret; } hidden_def(lgetfilecon_raw) int lgetfilecon(const char *path, char ** context) { int ret; char * rcontext = NULL; *context = NULL; ret = lgetfilecon_raw(path, &rcontext); if (ret > 0) { ret = selinux_raw_to_trans_context(rcontext, context); freecon(rcontext); } if (ret >= 0 && *context) return strlen(*context) + 1; return ret; } libselinux/src/libselinux.pc.in0100644 0000000 0000000 00000000437 13756670063 015702 0ustar000000000 0000000 prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ Name: libselinux Description: SELinux utility library Version: @VERSION@ URL: http://userspace.selinuxproject.org/ Requires.private: libsepol @PCRE_MODULE@ Libs: -L${libdir} -lselinux Cflags: -I${includedir} libselinux/src/load_policy.c0100644 0000000 0000000 00000030014 13756670063 015227 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include #include "selinux_internal.h" #ifndef ANDROID #include #include #endif #include #include "policy.h" #include #ifndef MNT_DETACH #define MNT_DETACH 2 #endif int security_load_policy(void *data, size_t len) { char path[PATH_MAX]; int fd, ret; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/load", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; ret = write(fd, data, len); close(fd); if (ret < 0) return -1; return 0; } hidden_def(security_load_policy) #ifndef ANDROID int load_setlocaldefs hidden = 1; #undef max #define max(a, b) (((a) > (b)) ? (a) : (b)) int selinux_mkload_policy(int preservebools) { int kernvers = security_policyvers(); int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers; int setlocaldefs = load_setlocaldefs; char path[PATH_MAX]; struct stat sb; struct utsname uts; size_t size; void *map, *data; int fd, rc = -1, prot; sepol_policydb_t *policydb; sepol_policy_file_t *pf; int usesepol = 0; int (*vers_max)(void) = NULL; int (*vers_min)(void) = NULL; int (*policy_file_create)(sepol_policy_file_t **) = NULL; void (*policy_file_free)(sepol_policy_file_t *) = NULL; void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL; int (*policydb_create)(sepol_policydb_t **) = NULL; void (*policydb_free)(sepol_policydb_t *) = NULL; int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL; int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL; int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL; int (*genbools_array)(void *data, size_t len, char **names, int *values, int nel) = NULL; int (*genusers)(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) = NULL; int (*genbools)(void *data, size_t len, const char *boolpath) = NULL; #ifdef SHARED char *errormsg = NULL; void *libsepolh = NULL; libsepolh = dlopen("libsepol.so.1", RTLD_NOW); if (libsepolh) { usesepol = 1; dlerror(); #define DLERR() if ((errormsg = dlerror())) goto dlclose; vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max"); DLERR(); vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min"); DLERR(); policy_file_create = dlsym(libsepolh, "sepol_policy_file_create"); DLERR(); policy_file_free = dlsym(libsepolh, "sepol_policy_file_free"); DLERR(); policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem"); DLERR(); policydb_create = dlsym(libsepolh, "sepol_policydb_create"); DLERR(); policydb_free = dlsym(libsepolh, "sepol_policydb_free"); DLERR(); policydb_read = dlsym(libsepolh, "sepol_policydb_read"); DLERR(); policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers"); DLERR(); policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image"); DLERR(); genbools_array = dlsym(libsepolh, "sepol_genbools_array"); DLERR(); genusers = dlsym(libsepolh, "sepol_genusers"); DLERR(); genbools = dlsym(libsepolh, "sepol_genbools"); DLERR(); #undef DLERR } #else usesepol = 1; vers_max = sepol_policy_kern_vers_max; vers_min = sepol_policy_kern_vers_min; policy_file_create = sepol_policy_file_create; policy_file_free = sepol_policy_file_free; policy_file_set_mem = sepol_policy_file_set_mem; policydb_create = sepol_policydb_create; policydb_free = sepol_policydb_free; policydb_read = sepol_policydb_read; policydb_set_vers = sepol_policydb_set_vers; policydb_to_image = sepol_policydb_to_image; genbools_array = sepol_genbools_array; genusers = sepol_genusers; genbools = sepol_genbools; #endif /* * Check whether we need to support local boolean and user definitions. */ if (setlocaldefs) { if (access(selinux_booleans_path(), F_OK) == 0) goto checkbool; snprintf(path, sizeof path, "%s.local", selinux_booleans_path()); if (access(path, F_OK) == 0) goto checkbool; snprintf(path, sizeof path, "%s/local.users", selinux_users_path()); if (access(path, F_OK) == 0) goto checkbool; /* No local definition files, so disable setlocaldefs. */ setlocaldefs = 0; } checkbool: /* * As of Linux 2.6.22, the kernel preserves boolean * values across a reload, so we do not need to * preserve them in userspace. */ if (preservebools && uname(&uts) == 0 && strverscmp(uts.release, "2.6.22") >= 0) preservebools = 0; if (usesepol) { maxvers = vers_max(); minvers = vers_min(); if (!setlocaldefs && !preservebools) maxvers = max(kernvers, maxvers); } vers = maxvers; search: snprintf(path, sizeof(path), "%s.%d", selinux_binary_policy_path(), vers); fd = open(path, O_RDONLY | O_CLOEXEC); while (fd < 0 && errno == ENOENT && --vers >= minvers) { /* Check prior versions to see if old policy is available */ snprintf(path, sizeof(path), "%s.%d", selinux_binary_policy_path(), vers); fd = open(path, O_RDONLY | O_CLOEXEC); } if (fd < 0) { fprintf(stderr, "SELinux: Could not open policy file <= %s.%d: %s\n", selinux_binary_policy_path(), maxvers, strerror(errno)); goto dlclose; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "SELinux: Could not stat policy file %s: %s\n", path, strerror(errno)); goto close; } prot = PROT_READ; if (setlocaldefs || preservebools) prot |= PROT_WRITE; size = sb.st_size; data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "SELinux: Could not map policy file %s: %s\n", path, strerror(errno)); goto close; } if (vers > kernvers && usesepol) { /* Need to downgrade to kernel-supported version. */ if (policy_file_create(&pf)) goto unmap; if (policydb_create(&policydb)) { policy_file_free(pf); goto unmap; } policy_file_set_mem(pf, data, size); if (policydb_read(policydb, pf)) { policy_file_free(pf); policydb_free(policydb); goto unmap; } if (policydb_set_vers(policydb, kernvers) || policydb_to_image(NULL, policydb, &data, &size)) { /* Downgrade failed, keep searching. */ fprintf(stderr, "SELinux: Could not downgrade policy file %s, searching for an older version.\n", path); policy_file_free(pf); policydb_free(policydb); munmap(map, sb.st_size); close(fd); vers--; goto search; } policy_file_free(pf); policydb_free(policydb); } if (usesepol) { if (setlocaldefs) { void *olddata = data; size_t oldsize = size; rc = genusers(olddata, oldsize, selinux_users_path(), &data, &size); if (rc < 0) { /* Fall back to the prior image if genusers failed. */ data = olddata; size = oldsize; rc = 0; } else { if (olddata != map) free(olddata); } } if (preservebools) { int *values, len, i; char **names; rc = security_get_boolean_names(&names, &len); if (!rc) { values = malloc(sizeof(int) * len); if (!values) { free(names); goto unmap; } for (i = 0; i < len; i++) values[i] = security_get_boolean_active(names[i]); (void)genbools_array(data, size, names, values, len); free(values); for (i = 0; i < len; i++) free(names[i]); free(names); } } else if (setlocaldefs) { (void)genbools(data, size, selinux_booleans_path()); } } rc = security_load_policy(data, size); if (rc) fprintf(stderr, "SELinux: Could not load policy file %s: %s\n", path, strerror(errno)); unmap: if (data != map) free(data); munmap(map, sb.st_size); close: close(fd); dlclose: #ifdef SHARED if (errormsg) fprintf(stderr, "libselinux: %s\n", errormsg); if (libsepolh) dlclose(libsepolh); #endif return rc; } hidden_def(selinux_mkload_policy) /* * Mount point for selinuxfs. * This definition is private to the function below. * Everything else uses the location determined during * libselinux startup via /proc/mounts (see init_selinuxmnt). * We only need the hardcoded definition for the initial mount * required for the initial policy load. */ int selinux_init_load_policy(int *enforce) { int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1; FILE *cfg; char *buf; /* * Reread the selinux configuration in case it has changed. * Example: Caller has chroot'd and is now loading policy from * chroot'd environment. */ selinux_reset_config(); /* * Get desired mode (disabled, permissive, enforcing) from * /etc/selinux/config. */ selinux_getenforcemode(&seconfig); /* Check for an override of the mode via the kernel command line. */ rc = mount("proc", "/proc", "proc", 0, 0); cfg = fopen("/proc/cmdline", "re"); if (cfg) { char *tmp; buf = malloc(selinux_page_size); if (!buf) { fclose(cfg); return -1; } if (fgets(buf, selinux_page_size, cfg) && (tmp = strstr(buf, "enforcing="))) { if (tmp == buf || isspace(*(tmp - 1))) { secmdline = atoi(tmp + sizeof("enforcing=") - 1); } } fclose(cfg); free(buf); } /* * Determine the final desired mode. * Command line argument takes precedence, then config file. */ if (secmdline >= 0) *enforce = secmdline; else if (seconfig >= 0) *enforce = seconfig; else *enforce = 0; /* unspecified or disabled */ /* * Check for the existence of SELinux via selinuxfs, and * mount it if present for use in the calls below. */ const char *mntpoint = NULL; /* First make sure /sys is mounted */ if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) { if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { mntpoint = SELINUXMNT; } else { /* check old mountpoint */ if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { mntpoint = OLDSELINUXMNT; } } } else { /* check old mountpoint */ if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { mntpoint = OLDSELINUXMNT; } } if (! mntpoint ) { if (errno == ENODEV || !selinuxfs_exists()) { /* * SELinux was disabled in the kernel, either * omitted entirely or disabled at boot via selinux=0. * This takes precedence over any config or * commandline enforcing setting. */ *enforce = 0; } else { /* Only emit this error if selinux was not disabled */ fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno)); } if (rc == 0) umount2("/proc", MNT_DETACH); goto noload; } set_selinuxmnt(mntpoint); if (rc == 0) umount2("/proc", MNT_DETACH); /* * Note: The following code depends on having selinuxfs * already mounted and selinuxmnt set above. */ if (seconfig == -1) { /* Runtime disable of SELinux. */ rc = security_disable(); if (rc == 0) { /* Successfully disabled, so umount selinuxfs too. */ umount(selinux_mnt); fini_selinuxmnt(); goto noload; } else { /* * It's possible that this failed because policy has * already been loaded. We can't disable SELinux now, * so the best we can do is force it to be permissive. */ *enforce = 0; } } /* * If necessary, change the kernel enforcing status to match * the desired mode. */ orig_enforce = rc = security_getenforce(); if (rc < 0) goto noload; if (orig_enforce != *enforce) { rc = security_setenforce(*enforce); if (rc < 0) { fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno)); if (*enforce) goto noload; } } if (seconfig == -1) { umount(selinux_mnt); fini_selinuxmnt(); goto noload; } /* Load the policy. */ return selinux_mkload_policy(0); noload: /* * Only return 0 on a successful completion of policy load. * In any other case, we want to return an error so that init * knows not to proceed with the re-exec for the domain transition. * Depending on the *enforce setting, init will halt (> 0) or proceed * normally (otherwise). */ return -1; } #endif libselinux/src/lsetfilecon.c0100644 0000000 0000000 00000001476 13756670063 015252 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" int lsetfilecon_raw(const char *path, const char * context) { int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); if (rc < 0 && errno == ENOTSUP) { char * ccontext = NULL; int err = errno; if ((lgetfilecon_raw(path, &ccontext) >= 0) && (strcmp(context,ccontext) == 0)) { rc = 0; } else { errno = err; } freecon(ccontext); } return rc; } hidden_def(lsetfilecon_raw) int lsetfilecon(const char *path, const char *context) { int ret; char * rcontext; if (selinux_trans_to_raw_context(context, &rcontext)) return -1; ret = lsetfilecon_raw(path, rcontext); freecon(rcontext); return ret; } libselinux/src/mapping.c0100644 0000000 0000000 00000012657 13756670063 014401 0ustar000000000 0000000 /* * Class and permission mappings. */ #include #include #include #include #include #include #include #include "callbacks.h" #include "mapping.h" #include "selinux_internal.h" /* * Class and permission mappings */ struct selinux_mapping { security_class_t value; /* real, kernel value */ unsigned num_perms; access_vector_t perms[sizeof(access_vector_t) * 8]; }; static struct selinux_mapping *current_mapping = NULL; static security_class_t current_mapping_size = 0; /* * Mapping setting function */ int selinux_set_mapping(struct security_class_mapping *map) { size_t size = sizeof(struct selinux_mapping); security_class_t i, j; unsigned k; bool print_unknown_handle = false; bool reject = (security_reject_unknown() == 1); bool deny = (security_deny_unknown() == 1); free(current_mapping); current_mapping = NULL; current_mapping_size = 0; if (avc_reset() < 0) goto err; /* Find number of classes in the input mapping */ if (!map) { errno = EINVAL; goto err; } i = 0; while (map[i].name) i++; /* Allocate space for the class records, plus one for class zero */ current_mapping = (struct selinux_mapping *)calloc(++i, size); if (!current_mapping) goto err; /* Store the raw class and permission values */ j = 0; while (map[j].name) { struct security_class_mapping *p_in = map + (j++); struct selinux_mapping *p_out = current_mapping + j; p_out->value = string_to_security_class(p_in->name); if (!p_out->value) { selinux_log(SELINUX_INFO, "SELinux: Class %s not defined in policy.\n", p_in->name); if (reject) goto err2; p_out->num_perms = 0; print_unknown_handle = true; continue; } k = 0; while (p_in->perms[k]) { /* An empty permission string skips ahead */ if (!*p_in->perms[k]) { k++; continue; } p_out->perms[k] = string_to_av_perm(p_out->value, p_in->perms[k]); if (!p_out->perms[k]) { selinux_log(SELINUX_INFO, "SELinux: Permission %s in class %s not defined in policy.\n", p_in->perms[k], p_in->name); if (reject) goto err2; print_unknown_handle = true; } k++; } p_out->num_perms = k; } if (print_unknown_handle) selinux_log(SELINUX_INFO, "SELinux: the above unknown classes and permissions will be %s\n", deny ? "denied" : "allowed"); /* Set the mapping size here so the above lookups are "raw" */ current_mapping_size = i; return 0; err2: free(current_mapping); current_mapping = NULL; current_mapping_size = 0; err: return -1; } /* * Get real, kernel values from mapped values */ security_class_t unmap_class(security_class_t tclass) { if (tclass < current_mapping_size) return current_mapping[tclass].value; /* If here no mapping set or the class requested is not valid. */ if (current_mapping_size != 0) { errno = EINVAL; return 0; } else return tclass; } access_vector_t unmap_perm(security_class_t tclass, access_vector_t tperm) { if (tclass < current_mapping_size) { unsigned i; access_vector_t kperm = 0; for (i=0; inum_perms; access_vector_t result; for (i = 0, result = 0; i < n; i++) { if (avd->allowed & mapping->perms[i]) result |= 1<perms[i]) result |= 1<allowed = result; for (i = 0, result = 0; i < n; i++) { if (avd->decided & mapping->perms[i]) result |= 1<perms[i]) result |= 1<decided = result; for (i = 0, result = 0; i < n; i++) if (avd->auditallow & mapping->perms[i]) result |= 1<auditallow = result; for (i = 0, result = 0; i < n; i++) { if (avd->auditdeny & mapping->perms[i]) result |= 1<perms[i]) result |= 1<num_perms since this indicates * a bug in the object manager. */ for (; i < (sizeof(result)*8); i++) result |= 1<auditdeny = result; } } libselinux/src/mapping.h0100644 0000000 0000000 00000001440 13756670063 014372 0ustar000000000 0000000 /* * This file describes the class and permission mappings used to * hide the kernel numbers from userspace by allowing userspace object * managers to specify a list of classes and permissions. */ #ifndef _SELINUX_MAPPING_H_ #define _SELINUX_MAPPING_H_ #include /* * Get real, kernel values from mapped values */ extern security_class_t unmap_class(security_class_t tclass); extern access_vector_t unmap_perm(security_class_t tclass, access_vector_t tperm); /* * Get mapped values from real, kernel values */ extern security_class_t map_class(security_class_t kclass); extern access_vector_t map_perm(security_class_t tclass, access_vector_t kperm); extern void map_decision(security_class_t tclass, struct av_decision *avd); #endif /* _SELINUX_MAPPING_H_ */ libselinux/src/matchmediacon.c0100644 0000000 0000000 00000002437 13756670063 015535 0ustar000000000 0000000 #include #include #include #include #include "selinux_internal.h" #include #include #include #include #include #include #include int matchmediacon(const char *media, char ** con) { const char *path = selinux_media_context_path(); FILE *infile; char *ptr, *ptr2 = NULL; int found = 0; char current_line[PATH_MAX]; if ((infile = fopen(path, "re")) == NULL) return -1; while (!feof_unlocked(infile)) { if (!fgets_unlocked(current_line, sizeof(current_line), infile)) { return -1; } if (current_line[strlen(current_line) - 1]) current_line[strlen(current_line) - 1] = 0; /* Skip leading whitespace before the partial context. */ ptr = current_line; while (*ptr && isspace(*ptr)) ptr++; if (!(*ptr)) continue; /* Find the end of the media context. */ ptr2 = ptr; while (*ptr2 && !isspace(*ptr2)) ptr2++; if (!(*ptr2)) continue; *ptr2++ = 0; if (strcmp(media, ptr) == 0) { found = 1; break; } } fclose(infile); if (!found) return -1; /* Skip whitespace. */ while (*ptr2 && isspace(*ptr2)) ptr2++; if (!(*ptr2)) { return -1; } if (selinux_raw_to_trans_context(ptr2, con)) { *con = NULL; return -1; } return 0; } libselinux/src/matchpathcon.c0100644 0000000 0000000 00000030112 13756670063 015401 0ustar000000000 0000000 #include #include #include #include #include "selinux_internal.h" #include "label_internal.h" #include "callbacks.h" #include static int (*myinvalidcon) (const char *p, unsigned l, char *c) = NULL; static int (*mycanoncon) (const char *p, unsigned l, char **c) = NULL; static void #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) #endif default_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } void #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) #endif (*myprintf) (const char *fmt,...) = &default_printf; int myprintf_compat = 0; void set_matchpathcon_printf(void (*f) (const char *fmt, ...)) { myprintf = f ? f : &default_printf; myprintf_compat = 1; } int compat_validate(struct selabel_handle *rec, struct selabel_lookup_rec *contexts, const char *path, unsigned lineno) { int rc; char **ctx = &contexts->ctx_raw; if (myinvalidcon) rc = myinvalidcon(path, lineno, *ctx); else if (mycanoncon) rc = mycanoncon(path, lineno, ctx); else { rc = selabel_validate(rec, contexts); if (rc < 0) { if (lineno) { COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid context %s\n", path, lineno, *ctx); } else { COMPAT_LOG(SELINUX_WARNING, "%s: has invalid context %s\n", path, *ctx); } } } return rc ? -1 : 0; } #ifndef BUILD_HOST static __thread struct selabel_handle *hnd; /* * An array for mapping integers to contexts */ static __thread char **con_array; static __thread int con_array_size; static __thread int con_array_used; static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; static int destructor_key_initialized = 0; static int add_array_elt(char *con) { if (con_array_size) { while (con_array_used >= con_array_size) { con_array_size *= 2; con_array = (char **)realloc(con_array, sizeof(char*) * con_array_size); if (!con_array) { con_array_size = con_array_used = 0; return -1; } } } else { con_array_size = 1000; con_array = (char **)malloc(sizeof(char*) * con_array_size); if (!con_array) { con_array_size = con_array_used = 0; return -1; } } con_array[con_array_used] = strdup(con); if (!con_array[con_array_used]) return -1; return con_array_used++; } static void free_array_elts(void) { con_array_size = con_array_used = 0; free(con_array); con_array = NULL; } void set_matchpathcon_invalidcon(int (*f) (const char *p, unsigned l, char *c)) { myinvalidcon = f; } static int default_canoncon(const char *path, unsigned lineno, char **context) { char *tmpcon; if (security_canonicalize_context_raw(*context, &tmpcon) < 0) { if (errno == ENOENT) return 0; if (lineno) myprintf("%s: line %u has invalid context %s\n", path, lineno, *context); else myprintf("%s: invalid context %s\n", path, *context); return 1; } free(*context); *context = tmpcon; return 0; } void set_matchpathcon_canoncon(int (*f) (const char *p, unsigned l, char **c)) { if (f) mycanoncon = f; else mycanoncon = &default_canoncon; } static __thread struct selinux_opt options[SELABEL_NOPT]; static __thread int notrans; void set_matchpathcon_flags(unsigned int flags) { int i; memset(options, 0, sizeof(options)); i = SELABEL_OPT_BASEONLY; options[i].type = i; options[i].value = (flags & MATCHPATHCON_BASEONLY) ? (char*)1 : NULL; i = SELABEL_OPT_VALIDATE; options[i].type = i; options[i].value = (flags & MATCHPATHCON_VALIDATE) ? (char*)1 : NULL; notrans = flags & MATCHPATHCON_NOTRANS; } /* * An association between an inode and a * specification. */ typedef struct file_spec { ino_t ino; /* inode number */ int specind; /* index of specification in spec */ char *file; /* full pathname for diagnostic messages about conflicts */ struct file_spec *next; /* next association in hash bucket chain */ } file_spec_t; /* * The hash table of associations, hashed by inode number. * Chaining is used for collisions, with elements ordered * by inode number in each bucket. Each hash bucket has a dummy * header. */ #define HASH_BITS 16 #define HASH_BUCKETS (1 << HASH_BITS) #define HASH_MASK (HASH_BUCKETS-1) static file_spec_t *fl_head; /* * Try to add an association between an inode and * a specification. If there is already an association * for the inode and it conflicts with this specification, * then use the specification that occurs later in the * specification array. */ int matchpathcon_filespec_add(ino_t ino, int specind, const char *file) { file_spec_t *prevfl, *fl; int h, ret; struct stat sb; if (!fl_head) { fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS); if (!fl_head) goto oom; memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS); } h = (ino + (ino >> HASH_BITS)) & HASH_MASK; for (prevfl = &fl_head[h], fl = fl_head[h].next; fl; prevfl = fl, fl = fl->next) { if (ino == fl->ino) { ret = lstat(fl->file, &sb); if (ret < 0 || sb.st_ino != ino) { fl->specind = specind; free(fl->file); fl->file = malloc(strlen(file) + 1); if (!fl->file) goto oom; strcpy(fl->file, file); return fl->specind; } if (!strcmp(con_array[fl->specind], con_array[specind])) return fl->specind; myprintf ("%s: conflicting specifications for %s and %s, using %s.\n", __FUNCTION__, file, fl->file, con_array[fl->specind]); free(fl->file); fl->file = malloc(strlen(file) + 1); if (!fl->file) goto oom; strcpy(fl->file, file); return fl->specind; } if (ino > fl->ino) break; } fl = malloc(sizeof(file_spec_t)); if (!fl) goto oom; fl->ino = ino; fl->specind = specind; fl->file = malloc(strlen(file) + 1); if (!fl->file) goto oom_freefl; strcpy(fl->file, file); fl->next = prevfl->next; prevfl->next = fl; return fl->specind; oom_freefl: free(fl); oom: myprintf("%s: insufficient memory for file label entry for %s\n", __FUNCTION__, file); return -1; } /* * Evaluate the association hash table distribution. */ void matchpathcon_filespec_eval(void) { file_spec_t *fl; int h, used, nel, len, longest; if (!fl_head) return; used = 0; longest = 0; nel = 0; for (h = 0; h < HASH_BUCKETS; h++) { len = 0; for (fl = fl_head[h].next; fl; fl = fl->next) { len++; } if (len) used++; if (len > longest) longest = len; nel += len; } myprintf ("%s: hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n", __FUNCTION__, nel, used, HASH_BUCKETS, longest); } /* * Destroy the association hash table. */ void matchpathcon_filespec_destroy(void) { file_spec_t *fl, *tmp; int h; free_array_elts(); if (!fl_head) return; for (h = 0; h < HASH_BUCKETS; h++) { fl = fl_head[h].next; while (fl) { tmp = fl; fl = fl->next; free(tmp->file); free(tmp); } fl_head[h].next = NULL; } free(fl_head); fl_head = NULL; } static void matchpathcon_thread_destructor(void __attribute__((unused)) *ptr) { matchpathcon_fini(); } void __attribute__((destructor)) matchpathcon_lib_destructor(void); void hidden __attribute__((destructor)) matchpathcon_lib_destructor(void) { if (destructor_key_initialized) __selinux_key_delete(destructor_key); } static void matchpathcon_init_once(void) { if (__selinux_key_create(&destructor_key, matchpathcon_thread_destructor) == 0) destructor_key_initialized = 1; } int matchpathcon_init_prefix(const char *path, const char *subset) { if (!mycanoncon) mycanoncon = default_canoncon; __selinux_once(once, matchpathcon_init_once); __selinux_setspecific(destructor_key, (void *)1); options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET; options[SELABEL_OPT_SUBSET].value = subset; options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH; options[SELABEL_OPT_PATH].value = path; hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT); return hnd ? 0 : -1; } hidden_def(matchpathcon_init_prefix) int matchpathcon_init(const char *path) { return matchpathcon_init_prefix(path, NULL); } void matchpathcon_fini(void) { free_array_elts(); if (hnd) { selabel_close(hnd); hnd = NULL; } } /* * We do not want to resolve a symlink to a real path if it is the final * component of the name. Thus we split the pathname on the last "/" and * determine a real path component of the first portion. We then have to * copy the last part back on to get the final real path. Wheww. */ int realpath_not_final(const char *name, char *resolved_path) { char *last_component; char *tmp_path, *p; size_t len = 0; int rc = 0; tmp_path = strdup(name); if (!tmp_path) { myprintf("symlink_realpath(%s) strdup() failed: %s\n", name, strerror(errno)); rc = -1; goto out; } last_component = strrchr(tmp_path, '/'); if (last_component == tmp_path) { last_component++; p = strcpy(resolved_path, ""); } else if (last_component) { *last_component = '\0'; last_component++; p = realpath(tmp_path, resolved_path); } else { last_component = tmp_path; p = realpath("./", resolved_path); } if (!p) { myprintf("symlink_realpath(%s) realpath() failed: %s\n", name, strerror(errno)); rc = -1; goto out; } len = strlen(p); if (len + strlen(last_component) + 2 > PATH_MAX) { myprintf("symlink_realpath(%s) failed: Filename too long \n", name); errno=ENAMETOOLONG; rc = -1; goto out; } resolved_path += len; strcpy(resolved_path, "/"); resolved_path += 1; strcpy(resolved_path, last_component); out: free(tmp_path); return rc; } int matchpathcon(const char *path, mode_t mode, char ** con) { char stackpath[PATH_MAX + 1]; char *p = NULL; if (!hnd && (matchpathcon_init_prefix(NULL, NULL) < 0)) return -1; if (S_ISLNK(mode)) { if (!realpath_not_final(path, stackpath)) path = stackpath; } else { p = realpath(path, stackpath); if (p) path = p; } return notrans ? selabel_lookup_raw(hnd, con, path, mode) : selabel_lookup(hnd, con, path, mode); } int matchpathcon_index(const char *name, mode_t mode, char ** con) { int i = matchpathcon(name, mode, con); if (i < 0) return -1; return add_array_elt(*con); } void matchpathcon_checkmatches(char *str __attribute__((unused))) { selabel_stats(hnd); } /* Compare two contexts to see if their differences are "significant", * or whether the only difference is in the user. */ int selinux_file_context_cmp(const char * a, const char * b) { char *rest_a, *rest_b; /* Rest of the context after the user */ if (!a && !b) return 0; if (!a) return -1; if (!b) return 1; rest_a = strchr((char *)a, ':'); rest_b = strchr((char *)b, ':'); if (!rest_a && !rest_b) return 0; if (!rest_a) return -1; if (!rest_b) return 1; return strcmp(rest_a, rest_b); } int selinux_file_context_verify(const char *path, mode_t mode) { char * con = NULL; char * fcontext = NULL; int rc = 0; char stackpath[PATH_MAX + 1]; char *p = NULL; if (S_ISLNK(mode)) { if (!realpath_not_final(path, stackpath)) path = stackpath; } else { p = realpath(path, stackpath); if (p) path = p; } rc = lgetfilecon_raw(path, &con); if (rc == -1) { if (errno != ENOTSUP) return -1; else return 0; } if (!hnd && (matchpathcon_init_prefix(NULL, NULL) < 0)) return -1; if (selabel_lookup_raw(hnd, &fcontext, path, mode) != 0) { if (errno != ENOENT) rc = -1; else rc = 0; } else { /* * Need to set errno to 0 as it can be set to ENOENT if the * file_contexts.subs file does not exist (see selabel_open in * label.c), thus causing confusion if errno is checked on return. */ errno = 0; rc = (selinux_file_context_cmp(fcontext, con) == 0); } freecon(con); freecon(fcontext); return rc; } int selinux_lsetfilecon_default(const char *path) { struct stat st; int rc = -1; char * scontext = NULL; if (lstat(path, &st) != 0) return rc; if (!hnd && (matchpathcon_init_prefix(NULL, NULL) < 0)) return -1; /* If there's an error determining the context, or it has none, return to allow default context */ if (selabel_lookup_raw(hnd, &scontext, path, st.st_mode)) { if (errno == ENOENT) rc = 0; } else { rc = lsetfilecon_raw(path, scontext); freecon(scontext); } return rc; } #endif libselinux/src/policy.h0100644 0000000 0000000 00000001353 13756670063 014241 0ustar000000000 0000000 #ifndef _POLICY_H_ #define _POLICY_H_ /* Private definitions used internally by libselinux. */ /* * xattr name for SELinux attributes. * This may have been exported via Kernel uapi header. */ #ifndef XATTR_NAME_SELINUX #define XATTR_NAME_SELINUX "security.selinux" #endif /* Initial length guess for getting contexts. */ #define INITCONTEXTLEN 255 /* selinux file system type */ #define SELINUXFS "selinuxfs" /* selinuxfs magic number */ #define SELINUX_MAGIC 0xf97cff8c /* Preferred selinux mount location */ #define SELINUXMNT "/sys/fs/selinux" #define OLDSELINUXMNT "/selinux" /* selinuxfs mount point */ extern char *selinux_mnt; #define FILECONTEXTS "/etc/security/selinux/file_contexts" #define DEFAULT_POLICY_VERSION 15 #endif libselinux/src/policyvers.c0100644 0000000 0000000 00000001431 13756670063 015131 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include #include "policy.h" #include "dso.h" #include int security_policyvers(void) { int fd, ret; char path[PATH_MAX]; char buf[20]; unsigned vers = DEFAULT_POLICY_VERSION; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/policyvers", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) { if (errno == ENOENT) return vers; else return -1; } memset(buf, 0, sizeof buf); ret = read(fd, buf, sizeof buf - 1); close(fd); if (ret < 0) return -1; if (sscanf(buf, "%u", &vers) != 1) return -1; return vers; } hidden_def(security_policyvers) libselinux/src/procattr.c0100644 0000000 0000000 00000016364 13756670063 014603 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #define UNSET (char *) -1 static __thread char *prev_current = UNSET; static __thread char * prev_exec = UNSET; static __thread char * prev_fscreate = UNSET; static __thread char * prev_keycreate = UNSET; static __thread char * prev_sockcreate = UNSET; static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; static int destructor_key_initialized = 0; static __thread char destructor_initialized; /* Bionic and glibc >= 2.30 declare gettid() system call wrapper in unistd.h and * has a definition for it */ #ifdef __BIONIC__ #define OVERRIDE_GETTID 0 #elif !defined(__GLIBC_PREREQ) #define OVERRIDE_GETTID 1 #elif !__GLIBC_PREREQ(2,30) #define OVERRIDE_GETTID 1 #else #define OVERRIDE_GETTID 0 #endif #if OVERRIDE_GETTID static pid_t gettid(void) { return syscall(__NR_gettid); } #endif static void procattr_thread_destructor(void __attribute__((unused)) *unused) { if (prev_current != UNSET) free(prev_current); if (prev_exec != UNSET) free(prev_exec); if (prev_fscreate != UNSET) free(prev_fscreate); if (prev_keycreate != UNSET) free(prev_keycreate); if (prev_sockcreate != UNSET) free(prev_sockcreate); } void __attribute__((destructor)) procattr_destructor(void); void hidden __attribute__((destructor)) procattr_destructor(void) { if (destructor_key_initialized) __selinux_key_delete(destructor_key); } static inline void init_thread_destructor(void) { if (destructor_initialized == 0) { __selinux_setspecific(destructor_key, (void *)1); destructor_initialized = 1; } } static void init_procattr(void) { if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) { destructor_key_initialized = 1; } } static int openattr(pid_t pid, const char *attr, int flags) { int fd, rc; char *path; pid_t tid; if (pid > 0) { rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr); } else if (pid == 0) { rc = asprintf(&path, "/proc/thread-self/attr/%s", attr); if (rc < 0) return -1; fd = open(path, flags | O_CLOEXEC); if (fd >= 0 || errno != ENOENT) goto out; free(path); tid = gettid(); rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr); } else { errno = EINVAL; return -1; } if (rc < 0) return -1; fd = open(path, flags | O_CLOEXEC); out: free(path); return fd; } static int getprocattrcon_raw(char ** context, pid_t pid, const char *attr) { char *buf; size_t size; int fd; ssize_t ret; int errno_hold; char * prev_context; __selinux_once(once, init_procattr); init_thread_destructor(); switch (attr[0]) { case 'c': prev_context = prev_current; break; case 'e': prev_context = prev_exec; break; case 'f': prev_context = prev_fscreate; break; case 'k': prev_context = prev_keycreate; break; case 's': prev_context = prev_sockcreate; break; case 'p': prev_context = NULL; break; default: errno = ENOENT; return -1; }; if (prev_context && prev_context != UNSET) { *context = strdup(prev_context); if (!(*context)) { return -1; } return 0; } fd = openattr(pid, attr, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } memset(buf, 0, size); do { ret = read(fd, buf, size - 1); } while (ret < 0 && errno == EINTR); if (ret < 0) goto out2; if (ret == 0) { *context = NULL; goto out2; } *context = strdup(buf); if (!(*context)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: errno_hold = errno; close(fd); errno = errno_hold; return ret; } static int getprocattrcon(char ** context, pid_t pid, const char *attr) { int ret; char * rcontext; ret = getprocattrcon_raw(&rcontext, pid, attr); if (!ret) { ret = selinux_raw_to_trans_context(rcontext, context); freecon(rcontext); } return ret; } static int setprocattrcon_raw(const char * context, pid_t pid, const char *attr) { int fd; ssize_t ret; int errno_hold; char **prev_context, *context2 = NULL; __selinux_once(once, init_procattr); init_thread_destructor(); switch (attr[0]) { case 'c': prev_context = &prev_current; break; case 'e': prev_context = &prev_exec; break; case 'f': prev_context = &prev_fscreate; break; case 'k': prev_context = &prev_keycreate; break; case 's': prev_context = &prev_sockcreate; break; default: errno = ENOENT; return -1; }; if (!context && !*prev_context) return 0; if (context && *prev_context && *prev_context != UNSET && !strcmp(context, *prev_context)) return 0; fd = openattr(pid, attr, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; if (context) { ret = -1; context2 = strdup(context); if (!context2) goto out; do { ret = write(fd, context2, strlen(context2) + 1); } while (ret < 0 && errno == EINTR); } else { do { ret = write(fd, NULL, 0); /* clear */ } while (ret < 0 && errno == EINTR); } out: errno_hold = errno; close(fd); errno = errno_hold; if (ret < 0) { free(context2); return -1; } else { if (*prev_context != UNSET) free(*prev_context); *prev_context = context2; return 0; } } static int setprocattrcon(const char * context, pid_t pid, const char *attr) { int ret; char * rcontext; if (selinux_trans_to_raw_context(context, &rcontext)) return -1; ret = setprocattrcon_raw(rcontext, pid, attr); freecon(rcontext); return ret; } #define getselfattr_def(fn, attr) \ int get##fn##_raw(char **c) \ { \ return getprocattrcon_raw(c, 0, #attr); \ } \ int get##fn(char **c) \ { \ return getprocattrcon(c, 0, #attr); \ } #define setselfattr_def(fn, attr) \ int set##fn##_raw(const char * c) \ { \ return setprocattrcon_raw(c, 0, #attr); \ } \ int set##fn(const char * c) \ { \ return setprocattrcon(c, 0, #attr); \ } #define all_selfattr_def(fn, attr) \ getselfattr_def(fn, attr) \ setselfattr_def(fn, attr) #define getpidattr_def(fn, attr) \ int get##fn##_raw(pid_t pid, char **c) \ { \ if (pid <= 0) { \ errno = EINVAL; \ return -1; \ } else { \ return getprocattrcon_raw(c, pid, #attr); \ } \ } \ int get##fn(pid_t pid, char **c) \ { \ if (pid <= 0) { \ errno = EINVAL; \ return -1; \ } else { \ return getprocattrcon(c, pid, #attr); \ } \ } all_selfattr_def(con, current) getpidattr_def(pidcon, current) getselfattr_def(prevcon, prev) all_selfattr_def(execcon, exec) all_selfattr_def(fscreatecon, fscreate) all_selfattr_def(sockcreatecon, sockcreate) all_selfattr_def(keycreatecon, keycreate) hidden_def(getcon_raw) hidden_def(getcon) hidden_def(getexeccon_raw) hidden_def(getfilecon_raw) hidden_def(getfilecon) hidden_def(getfscreatecon_raw) hidden_def(getkeycreatecon_raw) hidden_def(getpeercon_raw) hidden_def(getpidcon_raw) hidden_def(getprevcon_raw) hidden_def(getprevcon) hidden_def(getsockcreatecon_raw) hidden_def(setcon_raw) hidden_def(setexeccon_raw) hidden_def(setexeccon) hidden_def(setfilecon_raw) hidden_def(setfscreatecon_raw) hidden_def(setkeycreatecon_raw) hidden_def(setsockcreatecon_raw) libselinux/src/query_user_context.c0100644 0000000 0000000 00000012022 13756670063 016677 0ustar000000000 0000000 #include #include #include #include "selinux_internal.h" #include "context_internal.h" #include /* context_menu - given a list of contexts, presents a menu of security contexts * to the user. Returns the number (position in the list) of * the user selected context. */ static int context_menu(char ** list) { int i; /* array index */ int choice = 0; /* index of the user's choice */ char response[10]; /* string to hold the user's response */ printf("\n\n"); for (i = 0; list[i]; i++) printf("[%d] %s\n", i + 1, list[i]); while ((choice < 1) || (choice > i)) { printf("Enter number of choice: "); fflush(stdin); if (fgets(response, sizeof(response), stdin) == NULL) continue; fflush(stdin); choice = strtol(response, NULL, 10); } return (choice - 1); } /* query_user_context - given a list of context, allow the user to choose one. The * default is the first context in the list. Returns 0 on * success, -1 on failure */ int query_user_context(char ** list, char ** usercon) { char response[10]; /* The user's response */ int choice; /* The index in the list of the sid chosen by the user */ if (!list[0]) return -1; printf("\nYour default context is %s.\n", list[0]); if (list[1]) { printf("Do you want to choose a different one? [n]"); fflush(stdin); if (fgets(response, sizeof(response), stdin) == NULL) return -1; fflush(stdin); if ((response[0] == 'y') || (response[0] == 'Y')) { choice = context_menu(list); *usercon = strdup(list[choice]); if (!(*usercon)) return -1; return 0; } *usercon = strdup(list[0]); if (!(*usercon)) return -1; } else { *usercon = strdup(list[0]); if (!(*usercon)) return -1; } return 0; } /* get_field - given fieldstr - the "name" of a field, query the user * and set the new value of the field */ static void get_field(const char *fieldstr, char *newfield, int newfieldlen) { int done = 0; /* true if a non-empty field has been obtained */ while (!done) { /* Keep going until we get a value for the field */ printf("\tEnter %s ", fieldstr); fflush(stdin); if (fgets(newfield, newfieldlen, stdin) == NULL) continue; fflush(stdin); if (newfield[strlen(newfield) - 1] == '\n') newfield[strlen(newfield) - 1] = '\0'; if (strlen(newfield) == 0) { printf("You must enter a %s\n", fieldstr); } else { done = 1; } } } /* manual_user_enter_context - provides a way for a user to manually enter a * context in case the policy doesn't allow a list * to be obtained. * given the userid, queries the user and places the * context chosen by the user into usercon. Returns 0 * on success. */ int manual_user_enter_context(const char *user, char ** newcon) { char response[10]; /* Used to get yes or no answers from user */ char role[100]; /* The role requested by the user */ int rolelen = 100; char type[100]; /* The type requested by the user */ int typelen = 100; char level[100]; /* The level requested by the user */ int levellen = 100; int mls_enabled = is_selinux_mls_enabled(); context_t new_context; /* The new context chosen by the user */ char *user_context = NULL; /* String value of the user's context */ int done = 0; /* true if a valid sid has been obtained */ /* Initialize the context. How this is done depends on whether or not MLS is enabled */ if (mls_enabled) new_context = context_new("user:role:type:level"); else new_context = context_new("user:role:type"); if (!new_context) return -1; while (!done) { printf("Would you like to enter a security context? [y]"); if (fgets(response, sizeof(response), stdin) == NULL || (response[0] == 'n') || (response[0] == 'N')) { context_free(new_context); return -1; } /* Allow the user to enter each field of the context individually */ if (context_user_set(new_context, user)) { context_free(new_context); return -1; } get_field("role", role, rolelen); if (context_role_set(new_context, role)) { context_free(new_context); return -1; } get_field("type", type, typelen); if (context_type_set(new_context, type)) { context_free(new_context); return -1; } if (mls_enabled) { get_field("level", level, levellen); if (context_range_set(new_context, level)) { context_free(new_context); return -1; } } /* Get the string value of the context and see if it is valid. */ user_context = context_str(new_context); if (!user_context) { context_free(new_context); return -1; } if (!security_check_context(user_context)) done = 1; else printf("Not a valid security context\n"); } *newcon = strdup(user_context); context_free(new_context); if (!(*newcon)) return -1; return 0; } libselinux/src/regex.c0100644 0000000 0000000 00000031717 13756670063 014056 0ustar000000000 0000000 #include #include #include #include #include #include "regex.h" #include "label_file.h" #include "selinux_internal.h" #ifdef USE_PCRE2 #define REGEX_ARCH_SIZE_T PCRE2_SIZE #else #define REGEX_ARCH_SIZE_T size_t #endif #ifndef __BYTE_ORDER__ /* If the compiler doesn't define __BYTE_ORDER__, try to use the C * library header definitions. */ #include #ifndef __BYTE_ORDER #error Neither __BYTE_ORDER__ nor __BYTE_ORDER defined. Unable to determine endianness. #endif #define __ORDER_LITTLE_ENDIAN __LITTLE_ENDIAN #define __ORDER_BIG_ENDIAN __BIG_ENDIAN #define __BYTE_ORDER__ __BYTE_ORDER #endif #ifdef USE_PCRE2 char const *regex_arch_string(void) { static char arch_string_buffer[32]; static char const *arch_string = ""; char const *endianness = NULL; int rc; if (arch_string[0] == '\0') { if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) endianness = "el"; else if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) endianness = "eb"; if (!endianness) return NULL; rc = snprintf(arch_string_buffer, sizeof(arch_string_buffer), "%zu-%zu-%s", sizeof(void *), sizeof(REGEX_ARCH_SIZE_T), endianness); if (rc < 0) abort(); arch_string = &arch_string_buffer[0]; } return arch_string; } struct regex_data { pcre2_code *regex; /* compiled regular expression */ /* * match data block required for the compiled * pattern in pcre2 */ pcre2_match_data *match_data; pthread_mutex_t match_mutex; }; int regex_prepare_data(struct regex_data **regex, char const *pattern_string, struct regex_error_data *errordata) { memset(errordata, 0, sizeof(struct regex_error_data)); *regex = regex_data_create(); if (!(*regex)) return -1; (*regex)->regex = pcre2_compile( (PCRE2_SPTR)pattern_string, PCRE2_ZERO_TERMINATED, PCRE2_DOTALL, &errordata->error_code, &errordata->error_offset, NULL); if (!(*regex)->regex) { goto err; } (*regex)->match_data = pcre2_match_data_create_from_pattern((*regex)->regex, NULL); if (!(*regex)->match_data) { goto err; } return 0; err: regex_data_free(*regex); *regex = NULL; return -1; } char const *regex_version(void) { static char version_buf[256]; size_t len = pcre2_config(PCRE2_CONFIG_VERSION, NULL); if (len <= 0 || len > sizeof(version_buf)) return NULL; pcre2_config(PCRE2_CONFIG_VERSION, version_buf); return version_buf; } int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, int do_load_precompregex, bool *regex_compiled) { int rc; uint32_t entry_len; *regex_compiled = false; rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0) return -1; if (entry_len && do_load_precompregex) { /* * this should yield exactly one because we store one pattern at * a time */ rc = pcre2_serialize_get_number_of_codes(mmap_area->next_addr); if (rc != 1) return -1; *regex = regex_data_create(); if (!*regex) return -1; rc = pcre2_serialize_decode(&(*regex)->regex, 1, (PCRE2_SPTR)mmap_area->next_addr, NULL); if (rc != 1) goto err; (*regex)->match_data = pcre2_match_data_create_from_pattern((*regex)->regex, NULL); if (!(*regex)->match_data) goto err; *regex_compiled = true; } /* and skip the decoded bit */ rc = next_entry(NULL, mmap_area, entry_len); if (rc < 0) goto err; return 0; err: regex_data_free(*regex); *regex = NULL; return -1; } int regex_writef(struct regex_data *regex, FILE *fp, int do_write_precompregex) { int rc = 0; size_t len; PCRE2_SIZE serialized_size; uint32_t to_write = 0; PCRE2_UCHAR *bytes = NULL; if (do_write_precompregex) { /* encode the patter for serialization */ rc = pcre2_serialize_encode((const pcre2_code **)®ex->regex, 1, &bytes, &serialized_size, NULL); if (rc != 1) { rc = -1; goto out; } to_write = serialized_size; } /* write serialized pattern's size */ len = fwrite(&to_write, sizeof(uint32_t), 1, fp); if (len != 1) { rc = -1; goto out; } if (do_write_precompregex) { /* write serialized pattern */ len = fwrite(bytes, 1, to_write, fp); if (len != to_write) rc = -1; } out: if (bytes) pcre2_serialize_free(bytes); return rc; } void regex_data_free(struct regex_data *regex) { if (regex) { if (regex->regex) pcre2_code_free(regex->regex); if (regex->match_data) pcre2_match_data_free(regex->match_data); __pthread_mutex_destroy(®ex->match_mutex); free(regex); } } int regex_match(struct regex_data *regex, char const *subject, int partial) { int rc; __pthread_mutex_lock(®ex->match_mutex); rc = pcre2_match( regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0, partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data, NULL); __pthread_mutex_unlock(®ex->match_mutex); if (rc > 0) return REGEX_MATCH; switch (rc) { case PCRE2_ERROR_PARTIAL: return REGEX_MATCH_PARTIAL; case PCRE2_ERROR_NOMATCH: return REGEX_NO_MATCH; default: return REGEX_ERROR; } } /* * TODO Replace this compare function with something that actually compares the * regular expressions. * This compare function basically just compares the binary representations of * the automatons, and because this representation contains pointers and * metadata, it can only return a match if regex1 == regex2. * Preferably, this function would be replaced with an algorithm that computes * the equivalence of the automatons systematically. */ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) { int rc; size_t len1, len2; rc = pcre2_pattern_info(regex1->regex, PCRE2_INFO_SIZE, &len1); assert(rc == 0); rc = pcre2_pattern_info(regex2->regex, PCRE2_INFO_SIZE, &len2); assert(rc == 0); if (len1 != len2 || memcmp(regex1->regex, regex2->regex, len1)) return SELABEL_INCOMPARABLE; return SELABEL_EQUAL; } struct regex_data *regex_data_create(void) { struct regex_data *regex_data = (struct regex_data *)calloc(1, sizeof(struct regex_data)); __pthread_mutex_init(®ex_data->match_mutex, NULL); return regex_data; } #else // !USE_PCRE2 char const *regex_arch_string(void) { return "N/A"; } /* Prior to version 8.20, libpcre did not have pcre_free_study() */ #if (PCRE_MAJOR < 8 || (PCRE_MAJOR == 8 && PCRE_MINOR < 20)) #define pcre_free_study pcre_free #endif struct regex_data { int owned; /* * non zero if regex and pcre_extra is owned by this * structure and thus must be freed on destruction. */ pcre *regex; /* compiled regular expression */ union { pcre_extra *sd; /* pointer to extra compiled stuff */ pcre_extra lsd; /* used to hold the mmap'd version */ }; }; int regex_prepare_data(struct regex_data **regex, char const *pattern_string, struct regex_error_data *errordata) { memset(errordata, 0, sizeof(struct regex_error_data)); *regex = regex_data_create(); if (!(*regex)) return -1; (*regex)->regex = pcre_compile(pattern_string, PCRE_DOTALL, &errordata->error_buffer, &errordata->error_offset, NULL); if (!(*regex)->regex) goto err; (*regex)->owned = 1; (*regex)->sd = pcre_study((*regex)->regex, 0, &errordata->error_buffer); if (!(*regex)->sd && errordata->error_buffer) goto err; return 0; err: regex_data_free(*regex); *regex = NULL; return -1; } char const *regex_version(void) { return pcre_version(); } int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, int unused __attribute__((unused)), bool *regex_compiled) { int rc; uint32_t entry_len; size_t info_len; rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0 || !entry_len) return -1; *regex = regex_data_create(); if (!(*regex)) return -1; (*regex)->owned = 0; (*regex)->regex = (pcre *)mmap_area->next_addr; rc = next_entry(NULL, mmap_area, entry_len); if (rc < 0) goto err; /* * Check that regex lengths match. pcre_fullinfo() * also validates its magic number. */ rc = pcre_fullinfo((*regex)->regex, NULL, PCRE_INFO_SIZE, &info_len); if (rc < 0 || info_len != entry_len) goto err; rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0) goto err; if (entry_len) { (*regex)->lsd.study_data = (void *)mmap_area->next_addr; (*regex)->lsd.flags |= PCRE_EXTRA_STUDY_DATA; rc = next_entry(NULL, mmap_area, entry_len); if (rc < 0) goto err; /* Check that study data lengths match. */ rc = pcre_fullinfo((*regex)->regex, &(*regex)->lsd, PCRE_INFO_STUDYSIZE, &info_len); if (rc < 0 || info_len != entry_len) goto err; } *regex_compiled = true; return 0; err: regex_data_free(*regex); *regex = NULL; return -1; } static inline pcre_extra *get_pcre_extra(struct regex_data *regex) { if (!regex) return NULL; if (regex->owned) { return regex->sd; } else if (regex->lsd.study_data) { return ®ex->lsd; } else { return NULL; } } int regex_writef(struct regex_data *regex, FILE *fp, int unused __attribute__((unused))) { int rc; size_t len; uint32_t to_write; size_t size; pcre_extra *sd = get_pcre_extra(regex); /* determine the size of the pcre data in bytes */ rc = pcre_fullinfo(regex->regex, NULL, PCRE_INFO_SIZE, &size); if (rc < 0) return -1; /* write the number of bytes in the pcre data */ to_write = size; len = fwrite(&to_write, sizeof(uint32_t), 1, fp); if (len != 1) return -1; /* write the actual pcre data as a char array */ len = fwrite(regex->regex, 1, to_write, fp); if (len != to_write) return -1; if (sd) { /* determine the size of the pcre study info */ rc = pcre_fullinfo(regex->regex, sd, PCRE_INFO_STUDYSIZE, &size); if (rc < 0) return -1; } else size = 0; /* write the number of bytes in the pcre study data */ to_write = size; len = fwrite(&to_write, sizeof(uint32_t), 1, fp); if (len != 1) return -1; if (sd) { /* write the actual pcre study data as a char array */ len = fwrite(sd->study_data, 1, to_write, fp); if (len != to_write) return -1; } return 0; } void regex_data_free(struct regex_data *regex) { if (regex) { if (regex->owned) { if (regex->regex) pcre_free(regex->regex); if (regex->sd) pcre_free_study(regex->sd); } free(regex); } } int regex_match(struct regex_data *regex, char const *subject, int partial) { int rc; rc = pcre_exec(regex->regex, get_pcre_extra(regex), subject, strlen(subject), 0, partial ? PCRE_PARTIAL_SOFT : 0, NULL, 0); switch (rc) { case 0: return REGEX_MATCH; case PCRE_ERROR_PARTIAL: return REGEX_MATCH_PARTIAL; case PCRE_ERROR_NOMATCH: return REGEX_NO_MATCH; default: return REGEX_ERROR; } } /* * TODO Replace this compare function with something that actually compares the * regular expressions. * This compare function basically just compares the binary representations of * the automatons, and because this representation contains pointers and * metadata, it can only return a match if regex1 == regex2. * Preferably, this function would be replaced with an algorithm that computes * the equivalence of the automatons systematically. */ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) { int rc; size_t len1, len2; rc = pcre_fullinfo(regex1->regex, NULL, PCRE_INFO_SIZE, &len1); assert(rc == 0); rc = pcre_fullinfo(regex2->regex, NULL, PCRE_INFO_SIZE, &len2); assert(rc == 0); if (len1 != len2 || memcmp(regex1->regex, regex2->regex, len1)) return SELABEL_INCOMPARABLE; return SELABEL_EQUAL; } struct regex_data *regex_data_create(void) { return (struct regex_data *)calloc(1, sizeof(struct regex_data)); } #endif void regex_format_error(struct regex_error_data const *error_data, char *buffer, size_t buf_size) { unsigned the_end_length = buf_size > 4 ? 4 : buf_size; char *ptr = &buffer[buf_size - the_end_length]; int rc = 0; size_t pos = 0; if (!buffer || !buf_size) return; rc = snprintf(buffer, buf_size, "REGEX back-end error: "); if (rc < 0) /* * If snprintf fails it constitutes a logical error that needs * fixing. */ abort(); pos += rc; if (pos >= buf_size) goto truncated; if (error_data->error_offset > 0) { #ifdef USE_PCRE2 rc = snprintf(buffer + pos, buf_size - pos, "At offset %zu: ", error_data->error_offset); #else rc = snprintf(buffer + pos, buf_size - pos, "At offset %d: ", error_data->error_offset); #endif if (rc < 0) abort(); } pos += rc; if (pos >= buf_size) goto truncated; #ifdef USE_PCRE2 rc = pcre2_get_error_message(error_data->error_code, (PCRE2_UCHAR *)(buffer + pos), buf_size - pos); if (rc == PCRE2_ERROR_NOMEMORY) goto truncated; #else rc = snprintf(buffer + pos, buf_size - pos, "%s", error_data->error_buffer); if (rc < 0) abort(); if ((size_t)rc < strlen(error_data->error_buffer)) goto truncated; #endif return; truncated: /* replace end of string with "..." to indicate that it was truncated */ switch (the_end_length) { /* no break statements, fall-through is intended */ case 4: *ptr++ = '.'; /* FALLTHRU */ case 3: *ptr++ = '.'; /* FALLTHRU */ case 2: *ptr++ = '.'; /* FALLTHRU */ case 1: *ptr++ = '\0'; /* FALLTHRU */ default: break; } return; } libselinux/src/regex.h0100644 0000000 0000000 00000014722 13756670063 014060 0ustar000000000 0000000 #ifndef SRC_REGEX_H_ #define SRC_REGEX_H_ #include #include #ifdef USE_PCRE2 #include #else #include #endif #include "dso.h" enum { REGEX_MATCH, REGEX_MATCH_PARTIAL, REGEX_NO_MATCH, REGEX_ERROR = -1, }; struct regex_data; #ifdef USE_PCRE2 struct regex_error_data { int error_code; PCRE2_SIZE error_offset; }; #else struct regex_error_data { char const *error_buffer; int error_offset; }; #endif struct mmap_area; /** * regex_arch_string return a string that represents the pointer width, the * width of what the backend considers a size type, and the endianness of the * system that this library was build for. (e.g. for x86_64: "8-8-el"). * This is required when loading stored regular espressions. PCRE2 regular * expressions are not portable across architectures that do not have a * matching arch-string. */ char const *regex_arch_string(void) hidden; /** * regex_verison returns the version string of the underlying regular * regular expressions library. In the case of PCRE it just returns the * result of pcre_version(). In the case of PCRE2, the very first time this * function is called it allocates a buffer large enough to hold the version * string and reads the PCRE2_CONFIG_VERSION option to fill the buffer. * The allocated buffer will linger in memory until the calling process is being * reaped. * * It may return NULL on error. */ char const *regex_version(void) hidden; /** * This constructor function allocates a buffer for a regex_data structure. * The buffer is being initialized with zeroes. */ struct regex_data *regex_data_create(void) hidden; /** * This complementary destructor function frees the a given regex_data buffer. * It also frees any non NULL member pointers with the appropriate pcreX_X_free * function. For PCRE this function respects the extra_owned field and frees * the pcre_extra data conditionally. Calling this function on a NULL pointer is * save. */ void regex_data_free(struct regex_data *regex) hidden; /** * This function compiles the regular expression. Additionally, it prepares * data structures required by the different underlying engines. For PCRE * it calls pcre_study to generate optional data required for optimized * execution of the compiled pattern. In the case of PCRE2, it allocates * a pcre2_match_data structure of appropriate size to hold all possible * matches created by the pattern. * * @arg regex If successful, the structure returned through *regex was allocated * with regex_data_create and must be freed with regex_data_free. * @arg pattern_string The pattern string that is to be compiled. * @arg errordata A pointer to a regex_error_data structure must be passed * to this function. This structure depends on the underlying * implementation. It can be passed to regex_format_error * to generate a human readable error message. * @retval 0 on success * @retval -1 on error */ int regex_prepare_data(struct regex_data **regex, char const *pattern_string, struct regex_error_data *errordata) hidden; /** * This function loads a serialized precompiled pattern from a contiguous * data region given by map_area. * * @arg map_area Description of the memory region holding a serialized * representation of the precompiled pattern. * @arg regex If successful, the structure returned through *regex was allocated * with regex_data_create and must be freed with regex_data_free. * @arg do_load_precompregex If non-zero precompiled patterns get loaded from * the mmap region (ignored by PCRE1 back-end). * @arg regex_compiled Set to true if a precompiled pattern was loaded * into regex, otherwise set to false to indicate later * compilation must occur * * @retval 0 on success * @retval -1 on error */ int regex_load_mmap(struct mmap_area *map_area, struct regex_data **regex, int do_load_precompregex, bool *regex_compiled) hidden; /** * This function stores a precompiled regular expression to a file. * In the case of PCRE, it just dumps the binary representation of the * precomplied pattern into a file. In the case of PCRE2, it uses the * serialization function provided by the library. * * @arg regex The precomplied regular expression data. * @arg fp A file stream specifying the output file. * @arg do_write_precompregex If non-zero precompiled patterns are written to * the output file (ignored by PCRE1 back-end). */ int regex_writef(struct regex_data *regex, FILE *fp, int do_write_precompregex) hidden; /** * This function applies a precompiled pattern to a subject string and * returns whether or not a match was found. * * @arg regex The precompiled pattern. * @arg subject The subject string. * @arg partial Boolean indicating if partial matches are wanted. A nonzero * value is equivalent to specifying PCRE[2]_PARTIAL_SOFT as * option to pcre_exec of pcre2_match. * @retval REGEX_MATCH if a match was found * @retval REGEX_MATCH_PARTIAL if a partial match was found * @retval REGEX_NO_MATCH if no match was found * @retval REGEX_ERROR if an error was encountered during the execution of the * regular expression */ int regex_match(struct regex_data *regex, char const *subject, int partial) hidden; /** * This function compares two compiled regular expressions (regex1 and regex2). * It compares the binary representations of the compiled patterns. It is a very * crude approximation because the binary representation holds data like * reference counters, that has nothing to do with the actual state machine. * * @retval SELABEL_EQUAL if the pattern's binary representations are exactly * the same * @retval SELABEL_INCOMPARABLE otherwise */ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) hidden; /** * This function takes the error data returned by regex_prepare_data and turns * it in to a human readable error message. * If the buffer given to hold the error message is to small it truncates the * message and indicates the truncation with an ellipsis ("...") at the end of * the buffer. * * @arg error_data Error data as returned by regex_prepare_data. * @arg buffer String buffer to hold the formated error string. * @arg buf_size Total size of the given bufer in bytes. */ void regex_format_error(struct regex_error_data const *error_data, char *buffer, size_t buf_size) hidden; #endif /* SRC_REGEX_H_ */ libselinux/src/reject_unknown.c0100644 0000000 0000000 00000001344 13756670063 015770 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_reject_unknown(void) { int fd, ret, reject_unknown = 0; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof(path), "%s/reject_unknown", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; memset(buf, 0, sizeof(buf)); ret = read(fd, buf, sizeof(buf) - 1); close(fd); if (ret < 0) return -1; if (sscanf(buf, "%d", &reject_unknown) != 1) return -1; return reject_unknown; } hidden_def(security_reject_unknown); libselinux/src/selinux_check_securetty_context.c0100644 0000000 0000000 00000002017 13756670063 021432 0ustar000000000 0000000 #include #include #include #include #include #include "selinux_internal.h" #include "context_internal.h" int selinux_check_securetty_context(const char * tty_context) { char *line = NULL; char *start, *end = NULL; size_t line_len = 0; ssize_t len; int found = -1; FILE *fp; fp = fopen(selinux_securetty_types_path(), "re"); if (fp) { context_t con = context_new(tty_context); if (con) { const char *type = context_type_get(con); while ((len = getline(&line, &line_len, fp)) != -1) { if (line[len - 1] == '\n') line[len - 1] = 0; /* Skip leading whitespace. */ start = line; while (*start && isspace(*start)) start++; if (!(*start)) continue; end = start; while (*end && !isspace(*end)) end++; if (*end) *end++ = 0; if (!strcmp(type, start)) { found = 0; break; } } free(line); context_free(con); } fclose(fp); } return found; } hidden_def(selinux_check_securetty_context) libselinux/src/selinux_config.c0100644 0000000 0000000 00000026160 13756670063 015754 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include "policy.h" #include "selinux_internal.h" #include "get_default_type_internal.h" #define SELINUXDEFAULT "targeted" #define SELINUXTYPETAG "SELINUXTYPE=" #define SELINUXTAG "SELINUX=" #define SETLOCALDEFS "SETLOCALDEFS=" #define REQUIRESEUSERS "REQUIRESEUSERS=" /* Indices for file paths arrays. */ #define BINPOLICY 0 #define CONTEXTS_DIR 1 #define FILE_CONTEXTS 2 #define HOMEDIR_CONTEXTS 3 #define DEFAULT_CONTEXTS 4 #define USER_CONTEXTS 5 #define FAILSAFE_CONTEXT 6 #define DEFAULT_TYPE 7 #define BOOLEANS 8 #define MEDIA_CONTEXTS 9 #define REMOVABLE_CONTEXT 10 #define CUSTOMIZABLE_TYPES 11 #define USERS_DIR 12 #define SEUSERS 13 #define TRANSLATIONS 14 #define NETFILTER_CONTEXTS 15 #define FILE_CONTEXTS_HOMEDIR 16 #define FILE_CONTEXTS_LOCAL 17 #define SECURETTY_TYPES 18 #define X_CONTEXTS 19 #define COLORS 20 #define VIRTUAL_DOMAIN 21 #define VIRTUAL_IMAGE 22 #define FILE_CONTEXT_SUBS 23 #define SEPGSQL_CONTEXTS 24 #define FILE_CONTEXT_SUBS_DIST 25 #define LXC_CONTEXTS 26 #define BOOLEAN_SUBS 27 #define OPENSSH_CONTEXTS 28 #define SYSTEMD_CONTEXTS 29 #define SNAPPERD_CONTEXTS 30 #define OPENRC_CONTEXTS 31 #define NEL 32 /* Part of one-time lazy init */ static pthread_once_t once = PTHREAD_ONCE_INIT; static void init_selinux_config(void); /* New layout is relative to SELINUXDIR/policytype. */ static char *file_paths[NEL]; #define L1(l) L2(l) #define L2(l)str##l static const union file_path_suffixes_data { struct { #define S_(n, s) char L1(__LINE__)[sizeof(s)]; #include "file_path_suffixes.h" #undef S_ }; char str[0]; } file_path_suffixes_data = { { #define S_(n, s) s, #include "file_path_suffixes.h" #undef S_ } }; static const uint16_t file_path_suffixes_idx[NEL] = { #define S_(n, s) [n] = offsetof(union file_path_suffixes_data, L1(__LINE__)), #include "file_path_suffixes.h" #undef S_ }; #undef L1 #undef L2 int selinux_getenforcemode(int *enforce) { int ret = -1; FILE *cfg = fopen(SELINUXCONFIG, "re"); if (cfg) { char *buf; int len = sizeof(SELINUXTAG) - 1; buf = malloc(selinux_page_size); if (!buf) { fclose(cfg); return -1; } while (fgets_unlocked(buf, selinux_page_size, cfg)) { if (strncmp(buf, SELINUXTAG, len)) continue; if (!strncasecmp (buf + len, "enforcing", sizeof("enforcing") - 1)) { *enforce = 1; ret = 0; break; } else if (!strncasecmp (buf + len, "permissive", sizeof("permissive") - 1)) { *enforce = 0; ret = 0; break; } else if (!strncasecmp (buf + len, "disabled", sizeof("disabled") - 1)) { *enforce = -1; ret = 0; break; } } fclose(cfg); free(buf); } return ret; } hidden_def(selinux_getenforcemode) static char *selinux_policytype; int selinux_getpolicytype(char **type) { __selinux_once(once, init_selinux_config); if (!selinux_policytype) return -1; *type = strdup(selinux_policytype); return *type ? 0 : -1; } hidden_def(selinux_getpolicytype) static int setpolicytype(const char *type) { free(selinux_policytype); selinux_policytype = strdup(type); return selinux_policytype ? 0 : -1; } static char *selinux_policyroot = NULL; static const char *selinux_rootpath = SELINUXDIR; static void init_selinux_config(void) { int i, *intptr; size_t line_len; ssize_t len; char *line_buf = NULL, *buf_p, *value, *type = NULL, *end; FILE *fp; if (selinux_policyroot) return; fp = fopen(SELINUXCONFIG, "re"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); while ((len = getline(&line_buf, &line_len, fp)) > 0) { if (line_buf[len - 1] == '\n') line_buf[len - 1] = 0; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; if (*buf_p == '#' || *buf_p == 0) continue; if (!strncasecmp(buf_p, SELINUXTYPETAG, sizeof(SELINUXTYPETAG) - 1)) { type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1); if (!type) return; end = type + strlen(type) - 1; while ((end > type) && (isspace(*end) || iscntrl(*end))) { *end = 0; end--; } if (setpolicytype(type) != 0) { free(type); return; } free(type); continue; } else if (!strncmp(buf_p, SETLOCALDEFS, sizeof(SETLOCALDEFS) - 1)) { value = buf_p + sizeof(SETLOCALDEFS) - 1; intptr = &load_setlocaldefs; } else if (!strncmp(buf_p, REQUIRESEUSERS, sizeof(REQUIRESEUSERS) - 1)) { value = buf_p + sizeof(REQUIRESEUSERS) - 1; intptr = &require_seusers; } else { continue; } if (isdigit(*value)) *intptr = atoi(value); else if (strncasecmp(value, "true", sizeof("true") - 1)) *intptr = 1; else if (strncasecmp (value, "false", sizeof("false") - 1)) *intptr = 0; } free(line_buf); fclose(fp); } if (!selinux_policytype && setpolicytype(SELINUXDEFAULT) != 0) return; if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, selinux_policytype) == -1) return; for (i = 0; i < NEL; i++) if (asprintf(&file_paths[i], "%s%s", selinux_policyroot, file_path_suffixes_data.str + file_path_suffixes_idx[i]) == -1) return; } static void fini_selinux_policyroot(void) __attribute__ ((destructor)); static void fini_selinux_policyroot(void) { int i; free(selinux_policyroot); selinux_policyroot = NULL; for (i = 0; i < NEL; i++) { free(file_paths[i]); file_paths[i] = NULL; } free(selinux_policytype); selinux_policytype = NULL; } void selinux_reset_config(void) { fini_selinux_policyroot(); init_selinux_config(); } hidden_def(selinux_reset_config) static const char *get_path(int idx) { __selinux_once(once, init_selinux_config); return file_paths[idx]; } const char *selinux_default_type_path(void) { return get_path(DEFAULT_TYPE); } hidden_def(selinux_default_type_path) const char *selinux_policy_root(void) { __selinux_once(once, init_selinux_config); return selinux_policyroot; } int selinux_set_policy_root(const char *path) { int i; char *policy_type = strrchr(path, '/'); if (!policy_type) { errno = EINVAL; return -1; } policy_type++; fini_selinux_policyroot(); selinux_policyroot = strdup(path); if (! selinux_policyroot) return -1; if (setpolicytype(policy_type) != 0) return -1; for (i = 0; i < NEL; i++) if (asprintf(&file_paths[i], "%s%s", selinux_policyroot, file_path_suffixes_data.str + file_path_suffixes_idx[i]) == -1) return -1; return 0; } const char *selinux_path(void) { return selinux_rootpath; } hidden_def(selinux_path) const char *selinux_default_context_path(void) { return get_path(DEFAULT_CONTEXTS); } hidden_def(selinux_default_context_path) const char *selinux_securetty_types_path(void) { return get_path(SECURETTY_TYPES); } hidden_def(selinux_securetty_types_path) const char *selinux_failsafe_context_path(void) { return get_path(FAILSAFE_CONTEXT); } hidden_def(selinux_failsafe_context_path) const char *selinux_removable_context_path(void) { return get_path(REMOVABLE_CONTEXT); } hidden_def(selinux_removable_context_path) const char *selinux_binary_policy_path(void) { return get_path(BINPOLICY); } hidden_def(selinux_binary_policy_path) const char *selinux_current_policy_path(void) { int rc = 0; int vers = 0; static char policy_path[PATH_MAX]; if (selinux_mnt) { snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt); if (access(policy_path, F_OK) == 0 ) { return policy_path; } } vers = security_policyvers(); do { /* Check prior versions to see if old policy is available */ snprintf(policy_path, sizeof(policy_path), "%s.%d", selinux_binary_policy_path(), vers); } while ((rc = access(policy_path, F_OK)) && --vers > 0); if (rc) return NULL; return policy_path; } hidden_def(selinux_current_policy_path) const char *selinux_file_context_path(void) { return get_path(FILE_CONTEXTS); } hidden_def(selinux_file_context_path) const char *selinux_homedir_context_path(void) { return get_path(HOMEDIR_CONTEXTS); } hidden_def(selinux_homedir_context_path) const char *selinux_media_context_path(void) { return get_path(MEDIA_CONTEXTS); } hidden_def(selinux_media_context_path) const char *selinux_customizable_types_path(void) { return get_path(CUSTOMIZABLE_TYPES); } hidden_def(selinux_customizable_types_path) const char *selinux_contexts_path(void) { return get_path(CONTEXTS_DIR); } const char *selinux_user_contexts_path(void) { return get_path(USER_CONTEXTS); } hidden_def(selinux_user_contexts_path) const char *selinux_booleans_path(void) { return get_path(BOOLEANS); } hidden_def(selinux_booleans_path) const char *selinux_users_path(void) { return get_path(USERS_DIR); } hidden_def(selinux_users_path) const char *selinux_usersconf_path(void) { return get_path(SEUSERS); } hidden_def(selinux_usersconf_path) const char *selinux_translations_path(void) { return get_path(TRANSLATIONS); } hidden_def(selinux_translations_path) const char *selinux_colors_path(void) { return get_path(COLORS); } hidden_def(selinux_colors_path) const char *selinux_netfilter_context_path(void) { return get_path(NETFILTER_CONTEXTS); } hidden_def(selinux_netfilter_context_path) const char *selinux_file_context_homedir_path(void) { return get_path(FILE_CONTEXTS_HOMEDIR); } hidden_def(selinux_file_context_homedir_path) const char *selinux_file_context_local_path(void) { return get_path(FILE_CONTEXTS_LOCAL); } hidden_def(selinux_file_context_local_path) const char *selinux_x_context_path(void) { return get_path(X_CONTEXTS); } hidden_def(selinux_x_context_path) const char *selinux_virtual_domain_context_path(void) { return get_path(VIRTUAL_DOMAIN); } hidden_def(selinux_virtual_domain_context_path) const char *selinux_virtual_image_context_path(void) { return get_path(VIRTUAL_IMAGE); } hidden_def(selinux_virtual_image_context_path) const char *selinux_lxc_contexts_path(void) { return get_path(LXC_CONTEXTS); } hidden_def(selinux_lxc_contexts_path) const char *selinux_openrc_contexts_path(void) { return get_path(OPENRC_CONTEXTS); } hidden_def(selinux_openrc_contexts_path) const char *selinux_openssh_contexts_path(void) { return get_path(OPENSSH_CONTEXTS); } hidden_def(selinux_openssh_contexts_path) const char *selinux_snapperd_contexts_path(void) { return get_path(SNAPPERD_CONTEXTS); } hidden_def(selinux_snapperd_contexts_path) const char *selinux_systemd_contexts_path(void) { return get_path(SYSTEMD_CONTEXTS); } hidden_def(selinux_systemd_contexts_path) const char * selinux_booleans_subs_path(void) { return get_path(BOOLEAN_SUBS); } hidden_def(selinux_booleans_subs_path) const char * selinux_file_context_subs_path(void) { return get_path(FILE_CONTEXT_SUBS); } hidden_def(selinux_file_context_subs_path) const char * selinux_file_context_subs_dist_path(void) { return get_path(FILE_CONTEXT_SUBS_DIST); } hidden_def(selinux_file_context_subs_dist_path) const char *selinux_sepgsql_context_path(void) { return get_path(SEPGSQL_CONTEXTS); } hidden_def(selinux_sepgsql_context_path) libselinux/src/selinux_internal.h0100644 0000000 0000000 00000014172 13756670063 016330 0ustar000000000 0000000 #include #include #include "dso.h" hidden_proto(selinux_mkload_policy) hidden_proto(fini_selinuxmnt) hidden_proto(set_selinuxmnt) hidden_proto(selinuxfs_exists) hidden_proto(security_disable) hidden_proto(security_policyvers) hidden_proto(security_load_policy) hidden_proto(security_get_boolean_active) hidden_proto(security_get_boolean_names) hidden_proto(security_set_boolean) hidden_proto(security_commit_booleans) hidden_proto(security_check_context) hidden_proto(security_check_context_raw) hidden_proto(security_canonicalize_context) hidden_proto(security_canonicalize_context_raw) hidden_proto(security_compute_av) hidden_proto(security_compute_av_raw) hidden_proto(security_compute_av_flags) hidden_proto(security_compute_av_flags_raw) hidden_proto(security_compute_user) hidden_proto(security_compute_user_raw) hidden_proto(security_compute_create) hidden_proto(security_compute_create_raw) hidden_proto(security_compute_create_name) hidden_proto(security_compute_create_name_raw) hidden_proto(security_compute_member_raw) hidden_proto(security_compute_relabel_raw) hidden_proto(is_selinux_enabled) hidden_proto(is_selinux_mls_enabled) hidden_proto(freecon) hidden_proto(freeconary) hidden_proto(getprevcon) hidden_proto(getprevcon_raw) hidden_proto(getcon) hidden_proto(getcon_raw) hidden_proto(setcon_raw) hidden_proto(getpeercon_raw) hidden_proto(getpidcon_raw) hidden_proto(getexeccon_raw) hidden_proto(getfilecon) hidden_proto(getfilecon_raw) hidden_proto(lgetfilecon_raw) hidden_proto(fgetfilecon_raw) hidden_proto(setfilecon_raw) hidden_proto(lsetfilecon_raw) hidden_proto(fsetfilecon_raw) hidden_proto(setexeccon) hidden_proto(setexeccon_raw) hidden_proto(getfscreatecon_raw) hidden_proto(getkeycreatecon_raw) hidden_proto(getsockcreatecon_raw) hidden_proto(setfscreatecon_raw) hidden_proto(setkeycreatecon_raw) hidden_proto(setsockcreatecon_raw) hidden_proto(security_getenforce) hidden_proto(security_setenforce) hidden_proto(security_deny_unknown) hidden_proto(security_reject_unknown) hidden_proto(security_get_checkreqprot) hidden_proto(selinux_boolean_sub) hidden_proto(selinux_current_policy_path) hidden_proto(selinux_binary_policy_path) hidden_proto(selinux_booleans_subs_path) hidden_proto(selinux_default_context_path) hidden_proto(selinux_securetty_types_path) hidden_proto(selinux_failsafe_context_path) hidden_proto(selinux_removable_context_path) hidden_proto(selinux_virtual_domain_context_path) hidden_proto(selinux_virtual_image_context_path) hidden_proto(selinux_lxc_contexts_path) hidden_proto(selinux_file_context_path) hidden_proto(selinux_file_context_homedir_path) hidden_proto(selinux_file_context_local_path) hidden_proto(selinux_file_context_subs_dist_path) hidden_proto(selinux_file_context_subs_path) hidden_proto(selinux_netfilter_context_path) hidden_proto(selinux_homedir_context_path) hidden_proto(selinux_user_contexts_path) hidden_proto(selinux_booleans_path) hidden_proto(selinux_customizable_types_path) hidden_proto(selinux_media_context_path) hidden_proto(selinux_x_context_path) hidden_proto(selinux_sepgsql_context_path) hidden_proto(selinux_openrc_contexts_path) hidden_proto(selinux_openssh_contexts_path) hidden_proto(selinux_snapperd_contexts_path) hidden_proto(selinux_systemd_contexts_path) hidden_proto(selinux_path) hidden_proto(selinux_check_passwd_access) hidden_proto(selinux_check_securetty_context) hidden_proto(matchpathcon_init_prefix) hidden_proto(selinux_users_path) hidden_proto(selinux_usersconf_path); hidden_proto(selinux_translations_path); hidden_proto(selinux_colors_path); hidden_proto(selinux_getenforcemode); hidden_proto(selinux_getpolicytype); hidden_proto(selinux_raw_to_trans_context); hidden_proto(selinux_trans_to_raw_context); hidden_proto(selinux_raw_context_to_color); hidden_proto(security_get_initial_context); hidden_proto(security_get_initial_context_raw); hidden_proto(selinux_reset_config); hidden void flush_class_cache(void); extern int load_setlocaldefs hidden; extern int require_seusers hidden; extern int selinux_page_size hidden; /* Make pthread_once optional */ #pragma weak pthread_once #pragma weak pthread_key_create #pragma weak pthread_key_delete #pragma weak pthread_setspecific /* Call handler iff the first call. */ #define __selinux_once(ONCE_CONTROL, INIT_FUNCTION) \ do { \ if (pthread_once != NULL) \ pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ INIT_FUNCTION (); \ (ONCE_CONTROL) = 2; \ } \ } while (0) /* Pthread key macros */ #define __selinux_key_create(KEY, DESTRUCTOR) \ (pthread_key_create != NULL ? pthread_key_create(KEY, DESTRUCTOR) : -1) #define __selinux_key_delete(KEY) \ do { \ if (pthread_key_delete != NULL) \ pthread_key_delete(KEY); \ } while (0) #define __selinux_setspecific(KEY, VALUE) \ do { \ if (pthread_setspecific != NULL) \ pthread_setspecific(KEY, VALUE); \ } while (0) /* selabel_lookup() is only thread safe if we're compiled with pthreads */ #pragma weak pthread_mutex_init #pragma weak pthread_mutex_destroy #pragma weak pthread_mutex_lock #pragma weak pthread_mutex_unlock #define __pthread_mutex_init(LOCK, ATTR) \ do { \ if (pthread_mutex_init != NULL) \ pthread_mutex_init(LOCK, ATTR); \ } while (0) #define __pthread_mutex_destroy(LOCK) \ do { \ if (pthread_mutex_destroy != NULL) \ pthread_mutex_destroy(LOCK); \ } while (0) #define __pthread_mutex_lock(LOCK) \ do { \ if (pthread_mutex_lock != NULL) \ pthread_mutex_lock(LOCK); \ } while (0) #define __pthread_mutex_unlock(LOCK) \ do { \ if (pthread_mutex_unlock != NULL) \ pthread_mutex_unlock(LOCK); \ } while (0) #define SELINUXDIR "/etc/selinux/" #define SELINUXCONFIG SELINUXDIR "config" extern int has_selinux_config hidden; libselinux/src/selinux_netlink.h0100644 0000000 0000000 00000001154 13756670063 016154 0ustar000000000 0000000 /* * Netlink event notifications for SELinux. * * Author: James Morris */ #ifndef _LINUX_SELINUX_NETLINK_H #define _LINUX_SELINUX_NETLINK_H /* Message types. */ #define SELNL_MSG_BASE 0x10 enum { SELNL_MSG_SETENFORCE = SELNL_MSG_BASE, SELNL_MSG_POLICYLOAD, SELNL_MSG_MAX }; /* Multicast groups */ #define SELNL_GRP_NONE 0x00000000 #define SELNL_GRP_AVC 0x00000001 /* AVC notifications */ #define SELNL_GRP_ALL 0xffffffff /* Message structures */ struct selnl_msg_setenforce { int32_t val; }; struct selnl_msg_policyload { uint32_t seqno; }; #endif /* _LINUX_SELINUX_NETLINK_H */ libselinux/src/selinux_restorecon.c0100644 0000000 0000000 00000072351 13756670064 016676 0ustar000000000 0000000 /* * The majority of this code is from Android's * external/libselinux/src/android.c and upstream * selinux/policycoreutils/setfiles/restore.c * * See selinux_restorecon(3) for details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" #include "selinux_internal.h" #define RESTORECON_LAST "security.restorecon_last" #define SYS_PATH "/sys" #define SYS_PREFIX SYS_PATH "/" #define STAR_COUNT 1024 static struct selabel_handle *fc_sehandle = NULL; static unsigned char *fc_digest = NULL; static size_t fc_digest_len = 0; static char *rootpath = NULL; static int rootpathlen; /* Information on excluded fs and directories. */ struct edir { char *directory; size_t size; /* True if excluded by selinux_restorecon_set_exclude_list(3). */ bool caller_excluded; }; #define CALLER_EXCLUDED true static bool ignore_mounts; static int exclude_non_seclabel_mounts(void); static int exclude_count = 0; static struct edir *exclude_lst = NULL; static uint64_t fc_count = 0; /* Number of files processed so far */ static uint64_t efile_count; /* Estimated total number of files */ /* Store information on directories with xattr's. */ struct dir_xattr *dir_xattr_list; static struct dir_xattr *dir_xattr_last; /* restorecon_flags for passing to restorecon_sb() */ struct rest_flags { bool nochange; bool verbose; bool progress; bool mass_relabel; bool set_specctx; bool add_assoc; bool ignore_digest; bool recurse; bool userealpath; bool set_xdev; bool abort_on_error; bool syslog_changes; bool log_matches; bool ignore_noent; bool warnonnomatch; }; static void restorecon_init(void) { struct selabel_handle *sehandle = NULL; if (!fc_sehandle) { sehandle = selinux_restorecon_default_handle(); selinux_restorecon_set_sehandle(sehandle); } efile_count = 0; if (!ignore_mounts) efile_count = exclude_non_seclabel_mounts(); } static pthread_once_t fc_once = PTHREAD_ONCE_INIT; /* * Manage excluded directories: * remove_exclude() - This removes any conflicting entries as there could be * a case where a non-seclabel fs is mounted on /foo and * then a seclabel fs is mounted on top of it. * However if an entry has been added via * selinux_restorecon_set_exclude_list(3) do not remove. * * add_exclude() - Add a directory/fs to be excluded from labeling. If it * has already been added, then ignore. * * check_excluded() - Check if directory/fs is to be excluded when relabeling. * * file_system_count() - Calculates the number of files to be processed. * The count is only used if SELINUX_RESTORECON_PROGRESS * is set and a mass relabel is requested. * * exclude_non_seclabel_mounts() - Reads /proc/mounts to determine what * non-seclabel mounts to exclude from * relabeling. restorecon_init() will not * call this function if the * SELINUX_RESTORECON_IGNORE_MOUNTS * flag is set. * Setting SELINUX_RESTORECON_IGNORE_MOUNTS * is useful where there is a non-seclabel fs * mounted on /foo and then a seclabel fs is * mounted on a directory below this. */ static void remove_exclude(const char *directory) { int i; for (i = 0; i < exclude_count; i++) { if (strcmp(directory, exclude_lst[i].directory) == 0 && !exclude_lst[i].caller_excluded) { free(exclude_lst[i].directory); if (i != exclude_count - 1) exclude_lst[i] = exclude_lst[exclude_count - 1]; exclude_count--; return; } } } static int add_exclude(const char *directory, bool who) { struct edir *tmp_list, *current; size_t len = 0; int i; /* Check if already present. */ for (i = 0; i < exclude_count; i++) { if (strcmp(directory, exclude_lst[i].directory) == 0) return 0; } if (directory == NULL || directory[0] != '/') { selinux_log(SELINUX_ERROR, "Full path required for exclude: %s.\n", directory); errno = EINVAL; return -1; } tmp_list = realloc(exclude_lst, sizeof(struct edir) * (exclude_count + 1)); if (!tmp_list) goto oom; exclude_lst = tmp_list; len = strlen(directory); while (len > 1 && directory[len - 1] == '/') len--; current = (exclude_lst + exclude_count); current->directory = strndup(directory, len); if (!current->directory) goto oom; current->size = len; current->caller_excluded = who; exclude_count++; return 0; oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); return -1; } static int check_excluded(const char *file) { int i; for (i = 0; i < exclude_count; i++) { if (strncmp(file, exclude_lst[i].directory, exclude_lst[i].size) == 0) { if (file[exclude_lst[i].size] == 0 || file[exclude_lst[i].size] == '/') return 1; } } return 0; } static int file_system_count(char *name) { struct statvfs statvfs_buf; int nfile = 0; memset(&statvfs_buf, 0, sizeof(statvfs_buf)); if (!statvfs(name, &statvfs_buf)) nfile = statvfs_buf.f_files - statvfs_buf.f_ffree; return nfile; } /* * This is called once when selinux_restorecon() is first called. * Searches /proc/mounts for all file systems that do not support extended * attributes and adds them to the exclude directory table. File systems * that support security labels have the seclabel option, return * approximate total file count. */ static int exclude_non_seclabel_mounts(void) { struct utsname uts; FILE *fp; size_t len; ssize_t num; int index = 0, found = 0, nfile = 0; char *mount_info[4]; char *buf = NULL, *item; /* Check to see if the kernel supports seclabel */ if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0) return 0; if (is_selinux_enabled() <= 0) return 0; fp = fopen("/proc/mounts", "re"); if (!fp) return 0; while ((num = getline(&buf, &len, fp)) != -1) { found = 0; index = 0; item = strtok(buf, " "); while (item != NULL) { mount_info[index] = item; index++; if (index == 4) break; item = strtok(NULL, " "); } if (index < 4) { selinux_log(SELINUX_ERROR, "/proc/mounts record \"%s\" has incorrect format.\n", buf); continue; } /* Remove pre-existing entry */ remove_exclude(mount_info[1]); item = strtok(mount_info[3], ","); while (item != NULL) { if (strcmp(item, "seclabel") == 0) { found = 1; nfile += file_system_count(mount_info[1]); break; } item = strtok(NULL, ","); } /* Exclude mount points without the seclabel option */ if (!found) { if (add_exclude(mount_info[1], !CALLER_EXCLUDED) && errno == ENOMEM) assert(0); } } free(buf); fclose(fp); /* return estimated #Files + 5% for directories and hard links */ return nfile * 1.05; } /* Called by selinux_restorecon_xattr(3) to build a linked list of entries. */ static int add_xattr_entry(const char *directory, bool delete_nonmatch, bool delete_all) { char *sha1_buf = NULL; unsigned char *xattr_value = NULL; ssize_t xattr_size; size_t i; int rc, digest_result; struct dir_xattr *new_entry; if (!directory) { errno = EINVAL; return -1; } xattr_value = malloc(fc_digest_len); if (!xattr_value) goto oom; xattr_size = getxattr(directory, RESTORECON_LAST, xattr_value, fc_digest_len); if (xattr_size < 0) { free(xattr_value); return 1; } /* Convert entry to a hex encoded string. */ sha1_buf = malloc(xattr_size * 2 + 1); if (!sha1_buf) { free(xattr_value); goto oom; } for (i = 0; i < (size_t)xattr_size; i++) sprintf((&sha1_buf[i * 2]), "%02x", xattr_value[i]); rc = memcmp(fc_digest, xattr_value, fc_digest_len); digest_result = rc ? NOMATCH : MATCH; if ((delete_nonmatch && rc != 0) || delete_all) { digest_result = rc ? DELETED_NOMATCH : DELETED_MATCH; rc = removexattr(directory, RESTORECON_LAST); if (rc) { selinux_log(SELINUX_ERROR, "Error: %s removing xattr \"%s\" from: %s\n", strerror(errno), RESTORECON_LAST, directory); digest_result = ERROR; } } free(xattr_value); /* Now add entries to link list. */ new_entry = malloc(sizeof(struct dir_xattr)); if (!new_entry) goto oom; new_entry->next = NULL; new_entry->directory = strdup(directory); if (!new_entry->directory) { free(new_entry); free(sha1_buf); goto oom; } new_entry->digest = strdup(sha1_buf); if (!new_entry->digest) { free(new_entry->directory); free(new_entry); free(sha1_buf); goto oom; } new_entry->result = digest_result; if (!dir_xattr_list) { dir_xattr_list = new_entry; dir_xattr_last = new_entry; } else { dir_xattr_last->next = new_entry; dir_xattr_last = new_entry; } free(sha1_buf); return 0; oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); return -1; } /* * Support filespec services filespec_add(), filespec_eval() and * filespec_destroy(). * * selinux_restorecon(3) uses filespec services when the * SELINUX_RESTORECON_ADD_ASSOC flag is set for adding associations between * an inode and a specification. */ /* * The hash table of associations, hashed by inode number. Chaining is used * for collisions, with elements ordered by inode number in each bucket. * Each hash bucket has a dummy header. */ #define HASH_BITS 16 #define HASH_BUCKETS (1 << HASH_BITS) #define HASH_MASK (HASH_BUCKETS-1) /* * An association between an inode and a context. */ typedef struct file_spec { ino_t ino; /* inode number */ char *con; /* matched context */ char *file; /* full pathname */ struct file_spec *next; /* next association in hash bucket chain */ } file_spec_t; static file_spec_t *fl_head; /* * Try to add an association between an inode and a context. If there is a * different context that matched the inode, then use the first context * that matched. */ static int filespec_add(ino_t ino, const char *con, const char *file) { file_spec_t *prevfl, *fl; int h, ret; struct stat64 sb; if (!fl_head) { fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS); if (!fl_head) goto oom; memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS); } h = (ino + (ino >> HASH_BITS)) & HASH_MASK; for (prevfl = &fl_head[h], fl = fl_head[h].next; fl; prevfl = fl, fl = fl->next) { if (ino == fl->ino) { ret = lstat64(fl->file, &sb); if (ret < 0 || sb.st_ino != ino) { freecon(fl->con); free(fl->file); fl->file = strdup(file); if (!fl->file) goto oom; fl->con = strdup(con); if (!fl->con) goto oom; return 1; } if (strcmp(fl->con, con) == 0) return 1; selinux_log(SELINUX_ERROR, "conflicting specifications for %s and %s, using %s.\n", file, fl->file, fl->con); free(fl->file); fl->file = strdup(file); if (!fl->file) goto oom; return 1; } if (ino > fl->ino) break; } fl = malloc(sizeof(file_spec_t)); if (!fl) goto oom; fl->ino = ino; fl->con = strdup(con); if (!fl->con) goto oom_freefl; fl->file = strdup(file); if (!fl->file) goto oom_freefl; fl->next = prevfl->next; prevfl->next = fl; return 0; oom_freefl: free(fl); oom: selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); return -1; } /* * Evaluate the association hash table distribution. */ #ifdef DEBUG static void filespec_eval(void) { file_spec_t *fl; int h, used, nel, len, longest; if (!fl_head) return; used = 0; longest = 0; nel = 0; for (h = 0; h < HASH_BUCKETS; h++) { len = 0; for (fl = fl_head[h].next; fl; fl = fl->next) len++; if (len) used++; if (len > longest) longest = len; nel += len; } selinux_log(SELINUX_INFO, "filespec hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n", nel, used, HASH_BUCKETS, longest); } #else static void filespec_eval(void) { } #endif /* * Destroy the association hash table. */ static void filespec_destroy(void) { file_spec_t *fl, *tmp; int h; if (!fl_head) return; for (h = 0; h < HASH_BUCKETS; h++) { fl = fl_head[h].next; while (fl) { tmp = fl; fl = fl->next; freecon(tmp->con); free(tmp->file); free(tmp); } fl_head[h].next = NULL; } free(fl_head); fl_head = NULL; } /* * Called if SELINUX_RESTORECON_SET_SPECFILE_CTX is not set to check if * the type components differ, updating newtypecon if so. */ static int compare_types(char *curcon, char *newcon, char **newtypecon) { int types_differ = 0; context_t cona; context_t conb; int rc = 0; cona = context_new(curcon); if (!cona) { rc = -1; goto out; } conb = context_new(newcon); if (!conb) { context_free(cona); rc = -1; goto out; } types_differ = strcmp(context_type_get(cona), context_type_get(conb)); if (types_differ) { rc |= context_user_set(conb, context_user_get(cona)); rc |= context_role_set(conb, context_role_get(cona)); rc |= context_range_set(conb, context_range_get(cona)); if (!rc) { *newtypecon = strdup(context_str(conb)); if (!*newtypecon) { rc = -1; goto err; } } } err: context_free(cona); context_free(conb); out: return rc; } static int restorecon_sb(const char *pathname, const struct stat *sb, struct rest_flags *flags) { char *newcon = NULL; char *curcon = NULL; char *newtypecon = NULL; int rc; bool updated = false; const char *lookup_path = pathname; float pc; if (rootpath) { if (strncmp(rootpath, lookup_path, rootpathlen) != 0) { selinux_log(SELINUX_ERROR, "%s is not located in alt_rootpath %s\n", lookup_path, rootpath); return -1; } lookup_path += rootpathlen; } if (rootpath != NULL && lookup_path[0] == '\0') /* this is actually the root dir of the alt root. */ rc = selabel_lookup_raw(fc_sehandle, &newcon, "/", sb->st_mode); else rc = selabel_lookup_raw(fc_sehandle, &newcon, lookup_path, sb->st_mode); if (rc < 0) { if (errno == ENOENT && flags->warnonnomatch) selinux_log(SELINUX_INFO, "Warning no default label for %s\n", lookup_path); return 0; /* no match, but not an error */ } if (flags->progress) { fc_count++; if (fc_count % STAR_COUNT == 0) { if (flags->mass_relabel && efile_count > 0) { pc = (fc_count < efile_count) ? (100.0 * fc_count / efile_count) : 100; fprintf(stdout, "\r%-.1f%%", (double)pc); } else { fprintf(stdout, "\r%" PRIu64 "k", fc_count / STAR_COUNT); } fflush(stdout); } } if (flags->add_assoc) { rc = filespec_add(sb->st_ino, newcon, pathname); if (rc < 0) { selinux_log(SELINUX_ERROR, "filespec_add error: %s\n", pathname); freecon(newcon); return -1; } if (rc > 0) { /* Already an association and it took precedence. */ freecon(newcon); return 0; } } if (flags->log_matches) selinux_log(SELINUX_INFO, "%s matched by %s\n", pathname, newcon); if (lgetfilecon_raw(pathname, &curcon) < 0) { if (errno != ENODATA) goto err; curcon = NULL; } if (curcon == NULL || strcmp(curcon, newcon) != 0) { if (!flags->set_specctx && curcon && (is_context_customizable(curcon) > 0)) { if (flags->verbose) { selinux_log(SELINUX_INFO, "%s not reset as customized by admin to %s\n", pathname, curcon); } goto out; } if (!flags->set_specctx && curcon) { /* If types different then update newcon. */ rc = compare_types(curcon, newcon, &newtypecon); if (rc) goto err; if (newtypecon) { freecon(newcon); newcon = newtypecon; } else { goto out; } } if (!flags->nochange) { if (lsetfilecon(pathname, newcon) < 0) goto err; updated = true; } if (flags->verbose) selinux_log(SELINUX_INFO, "%s %s from %s to %s\n", updated ? "Relabeled" : "Would relabel", pathname, curcon, newcon); if (flags->syslog_changes && !flags->nochange) { if (curcon) syslog(LOG_INFO, "relabeling %s from %s to %s\n", pathname, curcon, newcon); else syslog(LOG_INFO, "labeling %s to %s\n", pathname, newcon); } } out: rc = 0; out1: freecon(curcon); freecon(newcon); return rc; err: selinux_log(SELINUX_ERROR, "Could not set context for %s: %s\n", pathname, strerror(errno)); rc = -1; goto out1; } /* * Public API */ /* selinux_restorecon(3) - Main function that is responsible for labeling */ int selinux_restorecon(const char *pathname_orig, unsigned int restorecon_flags) { struct rest_flags flags; flags.ignore_digest = (restorecon_flags & SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false; flags.nochange = (restorecon_flags & SELINUX_RESTORECON_NOCHANGE) ? true : false; flags.verbose = (restorecon_flags & SELINUX_RESTORECON_VERBOSE) ? true : false; flags.progress = (restorecon_flags & SELINUX_RESTORECON_PROGRESS) ? true : false; flags.mass_relabel = (restorecon_flags & SELINUX_RESTORECON_MASS_RELABEL) ? true : false; flags.recurse = (restorecon_flags & SELINUX_RESTORECON_RECURSE) ? true : false; flags.set_specctx = (restorecon_flags & SELINUX_RESTORECON_SET_SPECFILE_CTX) ? true : false; flags.userealpath = (restorecon_flags & SELINUX_RESTORECON_REALPATH) ? true : false; flags.set_xdev = (restorecon_flags & SELINUX_RESTORECON_XDEV) ? true : false; flags.add_assoc = (restorecon_flags & SELINUX_RESTORECON_ADD_ASSOC) ? true : false; flags.abort_on_error = (restorecon_flags & SELINUX_RESTORECON_ABORT_ON_ERROR) ? true : false; flags.syslog_changes = (restorecon_flags & SELINUX_RESTORECON_SYSLOG_CHANGES) ? true : false; flags.log_matches = (restorecon_flags & SELINUX_RESTORECON_LOG_MATCHES) ? true : false; flags.ignore_noent = (restorecon_flags & SELINUX_RESTORECON_IGNORE_NOENTRY) ? true : false; flags.warnonnomatch = true; ignore_mounts = (restorecon_flags & SELINUX_RESTORECON_IGNORE_MOUNTS) ? true : false; bool issys; bool setrestoreconlast = true; /* TRUE = set xattr RESTORECON_LAST * FALSE = don't use xattr */ struct stat sb; struct statfs sfsb; FTS *fts; FTSENT *ftsent; char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname; char *paths[2] = { NULL, NULL }; int fts_flags, error, sverrno; char *xattr_value = NULL; ssize_t size; dev_t dev_num = 0; if (flags.verbose && flags.progress) flags.verbose = false; __selinux_once(fc_once, restorecon_init); if (!fc_sehandle) return -1; if (fc_digest_len) { xattr_value = malloc(fc_digest_len); if (!xattr_value) return -1; } /* * Convert passed-in pathname to canonical pathname by resolving * realpath of containing dir, then appending last component name. */ if (flags.userealpath) { char *basename_cpy = strdup(pathname_orig); if (!basename_cpy) goto realpatherr; pathbname = basename(basename_cpy); if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) { pathname = realpath(pathname_orig, NULL); if (!pathname) { free(basename_cpy); goto realpatherr; } } else { char *dirname_cpy = strdup(pathname_orig); if (!dirname_cpy) { free(basename_cpy); goto realpatherr; } pathdname = dirname(dirname_cpy); pathdnamer = realpath(pathdname, NULL); free(dirname_cpy); if (!pathdnamer) { free(basename_cpy); goto realpatherr; } if (!strcmp(pathdnamer, "/")) error = asprintf(&pathname, "/%s", pathbname); else error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname); if (error < 0) { free(basename_cpy); goto oom; } } free(basename_cpy); } else { pathname = strdup(pathname_orig); if (!pathname) goto oom; } paths[0] = pathname; issys = (!strcmp(pathname, SYS_PATH) || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX) - 1)) ? true : false; if (lstat(pathname, &sb) < 0) { if (flags.ignore_noent && errno == ENOENT) { free(xattr_value); free(pathdnamer); free(pathname); return 0; } else { selinux_log(SELINUX_ERROR, "lstat(%s) failed: %s\n", pathname, strerror(errno)); error = -1; goto cleanup; } } /* Ignore restoreconlast if not a directory */ if ((sb.st_mode & S_IFDIR) != S_IFDIR) setrestoreconlast = false; if (!flags.recurse) { if (check_excluded(pathname)) { error = 0; goto cleanup; } error = restorecon_sb(pathname, &sb, &flags); goto cleanup; } /* Ignore restoreconlast on /sys */ if (issys) setrestoreconlast = false; /* Ignore restoreconlast on in-memory filesystems */ if (setrestoreconlast && statfs(pathname, &sfsb) == 0) { if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) setrestoreconlast = false; } if (setrestoreconlast) { size = getxattr(pathname, RESTORECON_LAST, xattr_value, fc_digest_len); if (!flags.ignore_digest && (size_t)size == fc_digest_len && memcmp(fc_digest, xattr_value, fc_digest_len) == 0) { selinux_log(SELINUX_INFO, "Skipping restorecon as matching digest on: %s\n", pathname); error = 0; goto cleanup; } } if (flags.set_xdev) fts_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV; else fts_flags = FTS_PHYSICAL | FTS_NOCHDIR; fts = fts_open(paths, fts_flags, NULL); if (!fts) goto fts_err; ftsent = fts_read(fts); if (!ftsent) goto fts_err; /* * Keep the inode of the first device. This is because the FTS_XDEV * flag tells fts not to descend into directories with different * device numbers, but fts will still give back the actual directory. * By saving the device number of the directory that was passed to * selinux_restorecon() and then skipping all actions on any * directories with a different device number when the FTS_XDEV flag * is set (from http://marc.info/?l=selinux&m=124688830500777&w=2). */ dev_num = ftsent->fts_statp->st_dev; error = 0; do { /* If the FTS_XDEV flag is set and the device is different */ if (flags.set_xdev && ftsent->fts_statp->st_dev != dev_num) continue; switch (ftsent->fts_info) { case FTS_DC: selinux_log(SELINUX_ERROR, "Directory cycle on %s.\n", ftsent->fts_path); errno = ELOOP; error = -1; goto out; case FTS_DP: continue; case FTS_DNR: selinux_log(SELINUX_ERROR, "Could not read %s: %s.\n", ftsent->fts_path, strerror(ftsent->fts_errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_NS: selinux_log(SELINUX_ERROR, "Could not stat %s: %s.\n", ftsent->fts_path, strerror(ftsent->fts_errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_ERR: selinux_log(SELINUX_ERROR, "Error on %s: %s.\n", ftsent->fts_path, strerror(ftsent->fts_errno)); fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_D: if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) { fts_set(fts, ftsent, FTS_SKIP); continue; } if (check_excluded(ftsent->fts_path)) { fts_set(fts, ftsent, FTS_SKIP); continue; } /* fall through */ default: error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, &flags); if (flags.warnonnomatch) flags.warnonnomatch = false; if (error && flags.abort_on_error) goto out; break; } } while ((ftsent = fts_read(fts)) != NULL); /* Labeling successful. Mark the top level directory as completed. */ if (setrestoreconlast && !flags.nochange && !error && fc_digest) { error = setxattr(pathname, RESTORECON_LAST, fc_digest, fc_digest_len, 0); if (!error && flags.verbose) selinux_log(SELINUX_INFO, "Updated digest for: %s\n", pathname); } out: if (flags.progress && flags.mass_relabel) fprintf(stdout, "\r%s 100.0%%\n", pathname); sverrno = errno; (void) fts_close(fts); errno = sverrno; cleanup: if (flags.add_assoc) { if (flags.verbose) filespec_eval(); filespec_destroy(); } free(pathdnamer); free(pathname); free(xattr_value); return error; oom: sverrno = errno; selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); errno = sverrno; error = -1; goto cleanup; realpatherr: sverrno = errno; selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n", pathname_orig, strerror(errno)); errno = sverrno; error = -1; goto cleanup; fts_err: selinux_log(SELINUX_ERROR, "fts error while labeling %s: %s\n", paths[0], strerror(errno)); error = -1; goto cleanup; } /* selinux_restorecon_set_sehandle(3) is called to set the global fc handle */ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl) { char **specfiles; size_t num_specfiles; fc_sehandle = (struct selabel_handle *) hndl; /* * Read digest if requested in selabel_open(3) and set global params. */ if (selabel_digest(fc_sehandle, &fc_digest, &fc_digest_len, &specfiles, &num_specfiles) < 0) { fc_digest = NULL; fc_digest_len = 0; } } /* * selinux_restorecon_default_handle(3) is called to set the global restorecon * handle by a process if the default params are required. */ struct selabel_handle *selinux_restorecon_default_handle(void) { struct selabel_handle *sehandle; struct selinux_opt fc_opts[] = { { SELABEL_OPT_DIGEST, (char *)1 } }; sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, 1); if (!sehandle) { selinux_log(SELINUX_ERROR, "Error obtaining file context handle: %s\n", strerror(errno)); return NULL; } return sehandle; } /* * selinux_restorecon_set_exclude_list(3) is called to add additional entries * to be excluded from labeling checks. */ void selinux_restorecon_set_exclude_list(const char **exclude_list) { int i; struct stat sb; for (i = 0; exclude_list[i]; i++) { if (lstat(exclude_list[i], &sb) < 0 && errno != EACCES) { selinux_log(SELINUX_ERROR, "lstat error on exclude path \"%s\", %s - ignoring.\n", exclude_list[i], strerror(errno)); break; } if (add_exclude(exclude_list[i], CALLER_EXCLUDED) && errno == ENOMEM) assert(0); } } /* selinux_restorecon_set_alt_rootpath(3) sets an alternate rootpath. */ int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath) { int len; /* This should be NULL on first use */ if (rootpath) free(rootpath); rootpath = strdup(alt_rootpath); if (!rootpath) { selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); return -1; } /* trim trailing /, if present */ len = strlen(rootpath); while (len && (rootpath[len - 1] == '/')) rootpath[--len] = '\0'; rootpathlen = len; return 0; } /* selinux_restorecon_xattr(3) - Find RESTORECON_LAST entries. */ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags, struct dir_xattr ***xattr_list) { bool recurse = (xattr_flags & SELINUX_RESTORECON_XATTR_RECURSE) ? true : false; bool delete_nonmatch = (xattr_flags & SELINUX_RESTORECON_XATTR_DELETE_NONMATCH_DIGESTS) ? true : false; bool delete_all = (xattr_flags & SELINUX_RESTORECON_XATTR_DELETE_ALL_DIGESTS) ? true : false; ignore_mounts = (xattr_flags & SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS) ? true : false; int rc, fts_flags; struct stat sb; struct statfs sfsb; struct dir_xattr *current, *next; FTS *fts; FTSENT *ftsent; char *paths[2] = { NULL, NULL }; __selinux_once(fc_once, restorecon_init); if (!fc_sehandle || !fc_digest_len) return -1; if (lstat(pathname, &sb) < 0) { if (errno == ENOENT) return 0; selinux_log(SELINUX_ERROR, "lstat(%s) failed: %s\n", pathname, strerror(errno)); return -1; } if (!recurse) { if (statfs(pathname, &sfsb) == 0) { if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) return 0; } if (check_excluded(pathname)) return 0; rc = add_xattr_entry(pathname, delete_nonmatch, delete_all); if (!rc && dir_xattr_list) *xattr_list = &dir_xattr_list; else if (rc == -1) return rc; return 0; } paths[0] = (char *)pathname; fts_flags = FTS_PHYSICAL | FTS_NOCHDIR; fts = fts_open(paths, fts_flags, NULL); if (!fts) { selinux_log(SELINUX_ERROR, "fts error on %s: %s\n", paths[0], strerror(errno)); return -1; } while ((ftsent = fts_read(fts)) != NULL) { switch (ftsent->fts_info) { case FTS_DP: continue; case FTS_D: if (statfs(ftsent->fts_path, &sfsb) == 0) { if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) continue; } if (check_excluded(ftsent->fts_path)) { fts_set(fts, ftsent, FTS_SKIP); continue; } rc = add_xattr_entry(ftsent->fts_path, delete_nonmatch, delete_all); if (rc == 1) continue; else if (rc == -1) goto cleanup; break; default: break; } } if (dir_xattr_list) *xattr_list = &dir_xattr_list; (void) fts_close(fts); return 0; cleanup: rc = errno; (void) fts_close(fts); errno = rc; if (dir_xattr_list) { /* Free any used memory */ current = dir_xattr_list; while (current) { next = current->next; free(current->directory); free(current->digest); free(current); current = next; } } return -1; } libselinux/src/selinuxswig.i0100644 0000000 0000000 00000003110 13756670064 015316 0ustar000000000 0000000 /* Authors: Dan Walsh * James Athey */ %module selinux %{ #include "../include/selinux/avc.h" #include "../include/selinux/context.h" #include "../include/selinux/get_context_list.h" #include "../include/selinux/get_default_type.h" #include "../include/selinux/label.h" #include "../include/selinux/restorecon.h" #include "../include/selinux/selinux.h" %} %apply int *OUTPUT { int *enforce }; %apply int *OUTPUT { size_t * }; %typedef unsigned mode_t; %typedef unsigned pid_t; %typemap(in, numinputs=0) (char ***names, int *len) (char **temp1=NULL, int temp2) { $1 = &temp1; $2 = &temp2; } %typemap(freearg) (char ***names, int *len) { int i; if (*$1) { for (i = 0; i < *$2; i++) { free((*$1)[i]); } free(*$1); } } %typemap(in, numinputs=0) (char ***) (char **temp=NULL) { $1 = &temp; } %typemap(freearg) (char ***) { if (*$1) freeconary(*$1); } /* Ignore functions that don't make sense when wrapped */ %ignore freecon; %ignore freeconary; /* Ignore functions that take a function pointer as an argument */ %ignore set_matchpathcon_printf; %ignore set_matchpathcon_invalidcon; %ignore set_matchpathcon_canoncon; %ignore avc_add_callback; /* Ignore netlink stuff for now */ %ignore avc_netlink_acquire_fd; %ignore avc_netlink_release_fd; %ignore avc_netlink_check_nb; %include "../include/selinux/avc.h" %include "../include/selinux/context.h" %include "../include/selinux/get_context_list.h" %include "../include/selinux/get_default_type.h" %include "../include/selinux/label.h" %include "../include/selinux/restorecon.h" %include "../include/selinux/selinux.h" libselinux/src/selinuxswig_python.i0100644 0000000 0000000 00000007513 13756670064 016732 0ustar000000000 0000000 /* Author: James Athey */ /* Never build rpm_execcon interface */ #ifndef DISABLE_RPM #define DISABLE_RPM #endif %module selinux %{ #include "selinux/selinux.h" %} %pythoncode %{ import shutil import os DISABLED = -1 PERMISSIVE = 0 ENFORCING = 1 def restorecon(path, recursive=False, verbose=False, force=False): """ Restore SELinux context on a given path Arguments: path -- The pathname for the file or directory to be relabeled. Keyword arguments: recursive -- Change files and directories file labels recursively (default False) verbose -- Show changes in file labels (default False) force -- Force reset of context to match file_context for customizable files, and the default file context, changing the user, role, range portion as well as the type (default False) """ restorecon_flags = SELINUX_RESTORECON_IGNORE_DIGEST | SELINUX_RESTORECON_REALPATH if recursive: restorecon_flags |= SELINUX_RESTORECON_RECURSE if verbose: restorecon_flags |= SELINUX_RESTORECON_VERBOSE if force: restorecon_flags |= SELINUX_RESTORECON_SET_SPECFILE_CTX selinux_restorecon(os.path.expanduser(path), restorecon_flags) def chcon(path, context, recursive=False): """ Set the SELinux context on a given path """ lsetfilecon(path, context) if recursive: for root, dirs, files in os.walk(path): for name in files + dirs: lsetfilecon(os.path.join(root, name), context) def copytree(src, dest): """ An SELinux-friendly shutil.copytree method """ shutil.copytree(src, dest) restorecon(dest, recursive=True) def install(src, dest): """ An SELinux-friendly shutil.move method """ shutil.move(src, dest) restorecon(dest, recursive=True) %} /* security_get_boolean_names() typemap */ %typemap(argout) (char ***names, int *len) { PyObject* list = PyList_New(*$2); int i; for (i = 0; i < *$2; i++) { PyList_SetItem(list, i, PyString_FromString((*$1)[i])); } $result = SWIG_Python_AppendOutput($result, list); } /* return a sid along with the result */ %typemap(argout) (security_id_t * sid) { if (*$1) { %append_output(SWIG_NewPointerObj(*$1, $descriptor(security_id_t), 0)); } else { Py_INCREF(Py_None); %append_output(Py_None); } } %typemap(in,numinputs=0) security_id_t *(security_id_t temp) { $1 = &temp; } %typemap(in, numinputs=0) void *(char *temp=NULL) { $1 = temp; } /* Makes security_compute_user() return a Python list of contexts */ %typemap(argout) (char ***con) { PyObject* plist; int i, len = 0; if (*$1) { while((*$1)[len]) len++; plist = PyList_New(len); for (i = 0; i < len; i++) { PyList_SetItem(plist, i, PyString_FromString((*$1)[i])); } } else { plist = PyList_New(0); } $result = SWIG_Python_AppendOutput($result, plist); } /* Makes functions in get_context_list.h return a Python list of contexts */ %typemap(argout) (char ***list) { PyObject* plist; int i; if (*$1) { plist = PyList_New(result); for (i = 0; i < result; i++) { PyList_SetItem(plist, i, PyString_FromString((*$1)[i])); } } else { plist = PyList_New(0); } /* Only return the Python list, don't need to return the length anymore */ $result = plist; } %typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) { $1 = &temp; } %typemap(freearg,match="in") char ** ""; %typemap(argout,noblock=1) char ** { if (*$1) { %append_output(SWIG_FromCharPtr(*$1)); freecon(*$1); } else { Py_INCREF(Py_None); %append_output(Py_None); } } %typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) { $1 = &temp; } %typemap(freearg,match="in") char ** ""; %typemap(argout,noblock=1) char ** { if (*$1) { %append_output(SWIG_FromCharPtr(*$1)); free(*$1); } else { Py_INCREF(Py_None); %append_output(Py_None); } } %include "selinuxswig_python_exception.i" %include "selinuxswig.i" libselinux/src/selinuxswig_ruby.i0100644 0000000 0000000 00000001710 13756670064 016363 0ustar000000000 0000000 /* Author: Dan Walsh Based on selinuxswig_python.i by James Athey */ /* Never build rpm_execcon interface */ #ifndef DISABLE_RPM #define DISABLE_RPM #endif %module selinux %{ #include "selinux/selinux.h" %} /* return a sid along with the result */ %typemap(argout) (security_id_t * sid) { if (*$1) { %append_output(SWIG_NewPointerObj(*$1, $descriptor(security_id_t), 0)); } } %typemap(in,numinputs=0) security_id_t *(security_id_t temp) { $1 = &temp; } %typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) { $1 = &temp; } %typemap(freearg,match="in") char ** ""; %typemap(argout,noblock=1) char ** { if (*$1) { %append_output(SWIG_FromCharPtr(*$1)); freecon(*$1); } } %typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) { $1 = &temp; } %typemap(freearg,match="in") char ** ""; %typemap(argout,noblock=1) char ** { if (*$1) { %append_output(SWIG_FromCharPtr(*$1)); free(*$1); } } %include "selinuxswig.i" libselinux/src/sestatus.c0100644 0000000 0000000 00000017110 13756670064 014607 0ustar000000000 0000000 /* * sestatus.c * * APIs to reference SELinux kernel status page (/selinux/status) * * Author: KaiGai Kohei * */ #include #include #include #include #include #include #include #include "avc_internal.h" #include "policy.h" /* * copied from the selinux/include/security.h */ struct selinux_status_t { uint32_t version; /* version number of thie structure */ uint32_t sequence; /* sequence number of seqlock logic */ uint32_t enforcing; /* current setting of enforcing mode */ uint32_t policyload; /* times of policy reloaded */ uint32_t deny_unknown; /* current setting of deny_unknown */ /* version > 0 support above status */ } __attribute((packed)); /* * `selinux_status' * * NULL : not initialized yet * MAP_FAILED : opened, but fallback-mode * Valid Pointer : opened and mapped correctly */ static struct selinux_status_t *selinux_status = NULL; static int selinux_status_fd; static uint32_t last_seqno; static uint32_t fallback_sequence; static int fallback_enforcing; static int fallback_policyload; /* * read_sequence * * A utility routine to reference kernel status page according to * seqlock logic. Since selinux_status->sequence is an odd value during * the kernel status page being updated, we try to synchronize completion * of this updating, but we assume it is rare. * The sequence is almost even number. * * __sync_synchronize is a portable memory barrier for various kind * of architecture that is supported by GCC. */ static inline uint32_t read_sequence(struct selinux_status_t *status) { uint32_t seqno = 0; do { /* * No need for sched_yield() in the first trial of * this loop. */ if (seqno & 0x0001) sched_yield(); seqno = status->sequence; __sync_synchronize(); } while (seqno & 0x0001); return seqno; } /* * selinux_status_updated * * It returns whether something has been happened since the last call. * Because `selinux_status->sequence' shall be always incremented on * both of setenforce/policyreload events, so differences from the last * value informs us something has been happened. */ int selinux_status_updated(void) { uint32_t curr_seqno; int result = 0; if (selinux_status == NULL) { errno = EINVAL; return -1; } if (selinux_status == MAP_FAILED) { if (avc_netlink_check_nb() < 0) return -1; curr_seqno = fallback_sequence; } else { curr_seqno = read_sequence(selinux_status); } /* * `curr_seqno' is always even-number, so it does not match with * `last_seqno' being initialized to odd-number in the first call. * We never return 'something was updated' in the first call, * because this function focuses on status-updating since the last * invocation. */ if (last_seqno & 0x0001) last_seqno = curr_seqno; if (last_seqno != curr_seqno) { last_seqno = curr_seqno; result = 1; } return result; } /* * selinux_status_getenforce * * It returns the current performing mode of SELinux. * 1 means currently we run in enforcing mode, or 0 means permissive mode. */ int selinux_status_getenforce(void) { uint32_t seqno; uint32_t enforcing; if (selinux_status == NULL) { errno = EINVAL; return -1; } if (selinux_status == MAP_FAILED) { if (avc_netlink_check_nb() < 0) return -1; return fallback_enforcing; } /* sequence must not be changed during references */ do { seqno = read_sequence(selinux_status); enforcing = selinux_status->enforcing; } while (seqno != read_sequence(selinux_status)); return enforcing ? 1 : 0; } /* * selinux_status_policyload * * It returns times of policy reloaded on the running system. * Note that it is not a reliable value on fallback-mode until it receives * the first event message via netlink socket, so, a correct usage of this * value is to compare it with the previous value to detect policy reloaded * event. */ int selinux_status_policyload(void) { uint32_t seqno; uint32_t policyload; if (selinux_status == NULL) { errno = EINVAL; return -1; } if (selinux_status == MAP_FAILED) { if (avc_netlink_check_nb() < 0) return -1; return fallback_policyload; } /* sequence must not be changed during references */ do { seqno = read_sequence(selinux_status); policyload = selinux_status->policyload; } while (seqno != read_sequence(selinux_status)); return policyload; } /* * selinux_status_deny_unknown * * It returns a guideline to handle undefined object classes or permissions. * 0 means SELinux treats policy queries on undefined stuff being allowed, * however, 1 means such queries are denied. */ int selinux_status_deny_unknown(void) { uint32_t seqno; uint32_t deny_unknown; if (selinux_status == NULL) { errno = EINVAL; return -1; } if (selinux_status == MAP_FAILED) return security_deny_unknown(); /* sequence must not be changed during references */ do { seqno = read_sequence(selinux_status); deny_unknown = selinux_status->deny_unknown; } while (seqno != read_sequence(selinux_status)); return deny_unknown ? 1 : 0; } /* * callback routines for fallback case using netlink socket */ static int fallback_cb_setenforce(int enforcing) { fallback_sequence += 2; fallback_enforcing = enforcing; return 0; } static int fallback_cb_policyload(int policyload) { fallback_sequence += 2; fallback_policyload = policyload; return 0; } /* * selinux_status_open * * It tries to open and mmap kernel status page (/selinux/status). * Since Linux 2.6.37 or later supports this feature, we may run * fallback routine using a netlink socket on older kernels, if * the supplied `fallback' is not zero. * It returns 0 on success, or -1 on error. */ int selinux_status_open(int fallback) { int fd; char path[PATH_MAX]; long pagesize; if (!selinux_mnt) { errno = ENOENT; return -1; } pagesize = sysconf(_SC_PAGESIZE); if (pagesize < 0) return -1; snprintf(path, sizeof(path), "%s/status", selinux_mnt); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) goto error; selinux_status = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); if (selinux_status == MAP_FAILED) { close(fd); goto error; } selinux_status_fd = fd; last_seqno = (uint32_t)(-1); return 0; error: /* * If caller wants fallback routine, we try to provide * an equivalent functionality using existing netlink * socket, although it needs system call invocation to * receive event notification. */ if (fallback && avc_netlink_open(0) == 0) { union selinux_callback cb; /* register my callbacks */ cb.func_setenforce = fallback_cb_setenforce; selinux_set_callback(SELINUX_CB_SETENFORCE, cb); cb.func_policyload = fallback_cb_policyload; selinux_set_callback(SELINUX_CB_POLICYLOAD, cb); /* mark as fallback mode */ selinux_status = MAP_FAILED; selinux_status_fd = avc_netlink_acquire_fd(); last_seqno = (uint32_t)(-1); fallback_sequence = 0; fallback_enforcing = security_getenforce(); fallback_policyload = 0; return 1; } selinux_status = NULL; return -1; } /* * selinux_status_close * * It unmap and close the kernel status page, or close netlink socket * if fallback mode. */ void selinux_status_close(void) { long pagesize; /* not opened */ if (selinux_status == NULL) return; /* fallback-mode */ if (selinux_status == MAP_FAILED) { avc_netlink_release_fd(); avc_netlink_close(); selinux_status = NULL; return; } pagesize = sysconf(_SC_PAGESIZE); /* not much we can do other than leak memory */ if (pagesize > 0) munmap(selinux_status, pagesize); selinux_status = NULL; close(selinux_status_fd); selinux_status_fd = -1; last_seqno = (uint32_t)(-1); } libselinux/src/setenforce.c0100644 0000000 0000000 00000001201 13756670064 015063 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include #include int security_setenforce(int value) { int fd, ret; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno = ENOENT; return -1; } snprintf(path, sizeof path, "%s/enforce", selinux_mnt); fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; snprintf(buf, sizeof buf, "%d", value); ret = write(fd, buf, strlen(buf)); close(fd); if (ret < 0) return -1; return 0; } hidden_def(security_setenforce) libselinux/src/setexecfilecon.c0100644 0000000 0000000 00000002512 13756670064 015734 0ustar000000000 0000000 #include #include #include #include "selinux_internal.h" #include "context_internal.h" int setexecfilecon(const char *filename, const char *fallback_type) { char * mycon = NULL, *fcon = NULL, *newcon = NULL; context_t con = NULL; int rc = 0; if (is_selinux_enabled() < 1) return 0; rc = getcon(&mycon); if (rc < 0) goto out; rc = getfilecon(filename, &fcon); if (rc < 0) goto out; rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &newcon); if (rc < 0) goto out; if (!strcmp(mycon, newcon)) { /* No default transition, use fallback_type for now. */ rc = -1; con = context_new(mycon); if (!con) goto out; if (context_type_set(con, fallback_type)) goto out; freecon(newcon); newcon = strdup(context_str(con)); if (!newcon) goto out; rc = 0; } rc = setexeccon(newcon); if (rc < 0) goto out; out: if (rc < 0 && security_getenforce() == 0) rc = 0; context_free(con); freecon(newcon); freecon(fcon); freecon(mycon); return rc < 0 ? rc : 0; } #ifndef DISABLE_RPM int rpm_execcon(unsigned int verified __attribute__ ((unused)), const char *filename, char *const argv[], char *const envp[]) { int rc; rc = setexecfilecon(filename, "rpm_script_t"); if (rc < 0) return rc; return execve(filename, argv, envp); } #endif libselinux/src/setfilecon.c0100644 0000000 0000000 00000001467 13756670064 015077 0ustar000000000 0000000 #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" int setfilecon_raw(const char *path, const char * context) { int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); if (rc < 0 && errno == ENOTSUP) { char * ccontext = NULL; int err = errno; if ((getfilecon_raw(path, &ccontext) >= 0) && (strcmp(context,ccontext) == 0)) { rc = 0; } else { errno = err; } freecon(ccontext); } return rc; } hidden_def(setfilecon_raw) int setfilecon(const char *path, const char *context) { int ret; char * rcontext; if (selinux_trans_to_raw_context(context, &rcontext)) return -1; ret = setfilecon_raw(path, rcontext); freecon(rcontext); return ret; } libselinux/src/setrans_client.c0100644 0000000 0000000 00000021600 13756670064 015750 0ustar000000000 0000000 /* Author: Trusted Computer Solutions, Inc. * * Modified: * Yuichi Nakamura - Stubs are used when DISABLE_SETRANS is defined, it is to reduce size for such as embedded devices. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dso.h" #include "selinux_internal.h" #include "setrans_internal.h" #ifndef DISABLE_SETRANS static unsigned char has_setrans; // Simple cache static __thread char * prev_t2r_trans = NULL; static __thread char * prev_t2r_raw = NULL; static __thread char * prev_r2t_trans = NULL; static __thread char * prev_r2t_raw = NULL; static __thread char *prev_r2c_trans = NULL; static __thread char * prev_r2c_raw = NULL; static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; static int destructor_key_initialized = 0; static __thread char destructor_initialized; /* * setransd_open * * This function opens a socket to the setransd. * Returns: on success, a file descriptor ( >= 0 ) to the socket * on error, a negative value */ static int setransd_open(void) { struct sockaddr_un addr; int fd; #ifdef SOCK_CLOEXEC fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd < 0 && errno == EINVAL) #endif { fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd >= 0) if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { close(fd); return -1; } } if (fd < 0) return -1; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)); if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { close(fd); return -1; } return fd; } /* Returns: 0 on success, <0 on failure */ static int send_request(int fd, uint32_t function, const char *data1, const char *data2) { struct msghdr msgh; struct iovec iov[5]; uint32_t data1_size; uint32_t data2_size; ssize_t count, expected; unsigned int i; if (fd < 0) return -1; if (!data1) data1 = ""; if (!data2) data2 = ""; data1_size = strlen(data1) + 1; data2_size = strlen(data2) + 1; iov[0].iov_base = &function; iov[0].iov_len = sizeof(function); iov[1].iov_base = &data1_size; iov[1].iov_len = sizeof(data1_size); iov[2].iov_base = &data2_size; iov[2].iov_len = sizeof(data2_size); iov[3].iov_base = (char *)data1; iov[3].iov_len = data1_size; iov[4].iov_base = (char *)data2; iov[4].iov_len = data2_size; memset(&msgh, 0, sizeof(msgh)); msgh.msg_iov = iov; msgh.msg_iovlen = sizeof(iov) / sizeof(iov[0]); expected = 0; for (i = 0; i < sizeof(iov) / sizeof(iov[0]); i++) expected += iov[i].iov_len; while (((count = sendmsg(fd, &msgh, MSG_NOSIGNAL)) < 0) && (errno == EINTR)) ; if (count < 0 || count != expected) return -1; return 0; } /* Returns: 0 on success, <0 on failure */ static int receive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val) { struct iovec resp_hdr[3]; uint32_t func; uint32_t data_size; char *data; struct iovec resp_data; ssize_t count; if (fd < 0) return -1; resp_hdr[0].iov_base = &func; resp_hdr[0].iov_len = sizeof(func); resp_hdr[1].iov_base = &data_size; resp_hdr[1].iov_len = sizeof(data_size); resp_hdr[2].iov_base = ret_val; resp_hdr[2].iov_len = sizeof(*ret_val); while (((count = readv(fd, resp_hdr, 3)) < 0) && (errno == EINTR)) ; if (count != (sizeof(func) + sizeof(data_size) + sizeof(*ret_val))) { return -1; } if (func != function || !data_size || data_size > MAX_DATA_BUF) { return -1; } data = malloc(data_size); if (!data) return -1; /* coveriety doesn't realize that data will be initialized in readv */ memset(data, 0, data_size); resp_data.iov_base = data; resp_data.iov_len = data_size; while (((count = readv(fd, &resp_data, 1))) < 0 && (errno == EINTR)) ; if (count < 0 || (uint32_t) count != data_size || data[data_size - 1] != '\0') { free(data); return -1; } *outdata = data; return 0; } static int raw_to_trans_context(const char *raw, char **transp) { int ret; int32_t ret_val; int fd; *transp = NULL; fd = setransd_open(); if (fd < 0) return fd; ret = send_request(fd, RAW_TO_TRANS_CONTEXT, raw, NULL); if (ret) goto out; ret = receive_response(fd, RAW_TO_TRANS_CONTEXT, transp, &ret_val); if (ret) goto out; ret = ret_val; out: close(fd); return ret; } static int trans_to_raw_context(const char *trans, char **rawp) { int ret; int32_t ret_val; int fd; *rawp = NULL; fd = setransd_open(); if (fd < 0) return fd; ret = send_request(fd, TRANS_TO_RAW_CONTEXT, trans, NULL); if (ret) goto out; ret = receive_response(fd, TRANS_TO_RAW_CONTEXT, rawp, &ret_val); if (ret) goto out; ret = ret_val; out: close(fd); return ret; } static int raw_context_to_color(const char *raw, char **colors) { int ret; int32_t ret_val; int fd; fd = setransd_open(); if (fd < 0) return fd; ret = send_request(fd, RAW_CONTEXT_TO_COLOR, raw, NULL); if (ret) goto out; ret = receive_response(fd, RAW_CONTEXT_TO_COLOR, colors, &ret_val); if (ret) goto out; ret = ret_val; out: close(fd); return ret; } static void setrans_thread_destructor(void __attribute__((unused)) *unused) { free(prev_t2r_trans); free(prev_t2r_raw); free(prev_r2t_trans); free(prev_r2t_raw); free(prev_r2c_trans); free(prev_r2c_raw); } void __attribute__((destructor)) setrans_lib_destructor(void); void hidden __attribute__((destructor)) setrans_lib_destructor(void) { if (!has_setrans) return; if (destructor_key_initialized) __selinux_key_delete(destructor_key); } static inline void init_thread_destructor(void) { if (!has_setrans) return; if (destructor_initialized == 0) { __selinux_setspecific(destructor_key, (void *)1); destructor_initialized = 1; } } static void init_context_translations(void) { has_setrans = (access(SETRANS_UNIX_SOCKET, F_OK) == 0); if (!has_setrans) return; if (__selinux_key_create(&destructor_key, setrans_thread_destructor) == 0) destructor_key_initialized = 1; } int selinux_trans_to_raw_context(const char * trans, char ** rawp) { if (!trans) { *rawp = NULL; return 0; } __selinux_once(once, init_context_translations); init_thread_destructor(); if (!has_setrans) { *rawp = strdup(trans); goto out; } if (prev_t2r_trans && strcmp(prev_t2r_trans, trans) == 0) { *rawp = strdup(prev_t2r_raw); } else { free(prev_t2r_trans); prev_t2r_trans = NULL; free(prev_t2r_raw); prev_t2r_raw = NULL; if (trans_to_raw_context(trans, rawp)) *rawp = strdup(trans); if (*rawp) { prev_t2r_trans = strdup(trans); if (!prev_t2r_trans) goto out; prev_t2r_raw = strdup(*rawp); if (!prev_t2r_raw) { free(prev_t2r_trans); prev_t2r_trans = NULL; } } } out: return *rawp ? 0 : -1; } hidden_def(selinux_trans_to_raw_context) int selinux_raw_to_trans_context(const char * raw, char ** transp) { if (!raw) { *transp = NULL; return 0; } __selinux_once(once, init_context_translations); init_thread_destructor(); if (!has_setrans) { *transp = strdup(raw); goto out; } if (prev_r2t_raw && strcmp(prev_r2t_raw, raw) == 0) { *transp = strdup(prev_r2t_trans); } else { free(prev_r2t_raw); prev_r2t_raw = NULL; free(prev_r2t_trans); prev_r2t_trans = NULL; if (raw_to_trans_context(raw, transp)) *transp = strdup(raw); if (*transp) { prev_r2t_raw = strdup(raw); if (!prev_r2t_raw) goto out; prev_r2t_trans = strdup(*transp); if (!prev_r2t_trans) { free(prev_r2t_raw); prev_r2t_raw = NULL; } } } out: return *transp ? 0 : -1; } hidden_def(selinux_raw_to_trans_context) int selinux_raw_context_to_color(const char * raw, char **transp) { if (!raw) { *transp = NULL; return -1; } __selinux_once(once, init_context_translations); init_thread_destructor(); if (!has_setrans) { *transp = strdup(raw); goto out; } if (prev_r2c_raw && strcmp(prev_r2c_raw, raw) == 0) { *transp = strdup(prev_r2c_trans); } else { free(prev_r2c_raw); prev_r2c_raw = NULL; free(prev_r2c_trans); prev_r2c_trans = NULL; if (raw_context_to_color(raw, transp)) return -1; if (*transp) { prev_r2c_raw = strdup(raw); if (!prev_r2c_raw) goto out; prev_r2c_trans = strdup(*transp); if (!prev_r2c_trans) { free(prev_r2c_raw); prev_r2c_raw = NULL; } } } out: return *transp ? 0 : -1; } hidden_def(selinux_raw_context_to_color) #else /*DISABLE_SETRANS*/ int selinux_trans_to_raw_context(const char * trans, char ** rawp) { if (!trans) { *rawp = NULL; return 0; } *rawp = strdup(trans); return *rawp ? 0 : -1; } hidden_def(selinux_trans_to_raw_context) int selinux_raw_to_trans_context(const char * raw, char ** transp) { if (!raw) { *transp = NULL; return 0; } *transp = strdup(raw); return *transp ? 0 : -1; } hidden_def(selinux_raw_to_trans_context) #endif /*DISABLE_SETRANS*/ libselinux/src/setrans_internal.h0100644 0000000 0000000 00000000412 13756670064 016311 0ustar000000000 0000000 /* Author: Trusted Computer Solutions, Inc. */ #include #define SETRANS_UNIX_SOCKET SELINUX_TRANS_DIR "/.setrans-unix" #define RAW_TO_TRANS_CONTEXT 2 #define TRANS_TO_RAW_CONTEXT 3 #define RAW_CONTEXT_TO_COLOR 4 #define MAX_DATA_BUF 8192 libselinux/src/seusers.c0100644 0000000 0000000 00000014330 13756670064 014426 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include "selinux_internal.h" /* Process line from seusers.conf and split into its fields. Returns 0 on success, -1 on comments, and -2 on error. */ static int process_seusers(const char *buffer, char **luserp, char **seuserp, char **levelp, int mls_enabled) { char *newbuf = strdup(buffer); char *luser = NULL, *seuser = NULL, *level = NULL; char *start, *end; int mls_found = 1; if (!newbuf) goto err; start = newbuf; while (isspace(*start)) start++; if (*start == '#' || *start == 0) { free(newbuf); return -1; /* Comment or empty line, skip over */ } end = strchr(start, ':'); if (!end) goto err; *end = 0; luser = strdup(start); if (!luser) goto err; start = end + 1; end = strchr(start, ':'); if (!end) { mls_found = 0; end = start; while (*end && !isspace(*end)) end++; } *end = 0; seuser = strdup(start); if (!seuser) goto err; if (!strcmp(seuser, "")) goto err; /* Skip MLS if disabled, or missing. */ if (!mls_enabled || !mls_found) goto out; start = ++end; while (*end && !isspace(*end)) end++; *end = 0; level = strdup(start); if (!level) goto err; if (!strcmp(level, "")) goto err; out: free(newbuf); *luserp = luser; *seuserp = seuser; *levelp = level; return 0; err: free(newbuf); free(luser); free(seuser); free(level); return -2; /* error */ } int require_seusers hidden = 0; #include #include static gid_t get_default_gid(const char *name) { struct passwd pwstorage, *pwent = NULL; gid_t gid = -1; /* Allocate space for the getpwnam_r buffer */ long rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (rbuflen <= 0) return -1; char *rbuf = malloc(rbuflen); if (rbuf == NULL) return -1; int retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); if (retval == 0 && pwent) { gid = pwent->pw_gid; } free(rbuf); return gid; } static int check_group(const char *group, const char *name, const gid_t gid) { int match = 0; int i, ng = 0; gid_t *groups = NULL; struct group gbuf, *grent = NULL; long rbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (rbuflen <= 0) return 0; char *rbuf; while(1) { rbuf = malloc(rbuflen); if (rbuf == NULL) return 0; int retval = getgrnam_r(group, &gbuf, rbuf, rbuflen, &grent); if ( retval == ERANGE ) { free(rbuf); rbuflen = rbuflen * 2; } else if ( retval != 0 || grent == NULL ) { goto done; } else { break; } } if (getgrouplist(name, gid, NULL, &ng) < 0) { if (ng == 0) goto done; groups = calloc(ng, sizeof(*groups)); if (!groups) goto done; if (getgrouplist(name, gid, groups, &ng) < 0) goto done; } else { /* WTF? ng was 0 and we didn't fail? Are we in 0 groups? */ goto done; } for (i = 0; i < ng; i++) { if (grent->gr_gid == groups[i]) { match = 1; goto done; } } done: free(groups); free(rbuf); return match; } int getseuserbyname(const char *name, char **r_seuser, char **r_level) { FILE *cfg = NULL; size_t size = 0; char *buffer = NULL; int rc; unsigned long lineno = 0; int mls_enabled = is_selinux_mls_enabled(); char *username = NULL; char *seuser = NULL; char *level = NULL; char *groupseuser = NULL; char *grouplevel = NULL; char *defaultseuser = NULL; char *defaultlevel = NULL; gid_t gid = get_default_gid(name); cfg = fopen(selinux_usersconf_path(), "re"); if (!cfg) goto nomatch; __fsetlocking(cfg, FSETLOCKING_BYCALLER); while (getline(&buffer, &size, cfg) > 0) { ++lineno; rc = process_seusers(buffer, &username, &seuser, &level, mls_enabled); if (rc == -1) continue; /* comment, skip */ if (rc == -2) { fprintf(stderr, "%s: error on line %lu, skipping...\n", selinux_usersconf_path(), lineno); continue; } if (!strcmp(username, name)) break; if (username[0] == '%' && !groupseuser && check_group(&username[1], name, gid)) { groupseuser = seuser; grouplevel = level; } else { if (!defaultseuser && !strcmp(username, "__default__")) { defaultseuser = seuser; defaultlevel = level; } else { free(seuser); free(level); } } free(username); username = NULL; seuser = NULL; } free(buffer); fclose(cfg); if (seuser) { free(username); free(defaultseuser); free(defaultlevel); free(groupseuser); free(grouplevel); *r_seuser = seuser; *r_level = level; return 0; } if (groupseuser) { free(defaultseuser); free(defaultlevel); *r_seuser = groupseuser; *r_level = grouplevel; return 0; } if (defaultseuser) { *r_seuser = defaultseuser; *r_level = defaultlevel; return 0; } nomatch: if (require_seusers) return -1; /* Fall back to the Linux username and no level. */ *r_seuser = strdup(name); if (!(*r_seuser)) return -1; *r_level = NULL; return 0; } int getseuser(const char *username, const char *service, char **r_seuser, char **r_level) { int ret = -1; int len = 0; char *seuser = NULL; char *level = NULL; char *buffer = NULL; size_t size = 0; char *rec = NULL; char *path=NULL; FILE *fp = NULL; if (asprintf(&path,"%s/logins/%s", selinux_policy_root(), username) < 0) goto err; fp = fopen(path, "re"); free(path); if (fp == NULL) goto err; __fsetlocking(fp, FSETLOCKING_BYCALLER); while (getline(&buffer, &size, fp) > 0) { if (strncmp(buffer, "*:", 2) == 0) { free(rec); rec = strdup(buffer); continue; } if (!service) continue; len = strlen(service); if ((strncmp(buffer, service, len) == 0) && (buffer[len] == ':')) { free(rec); rec = strdup(buffer); break; } } if (! rec) goto err; seuser = strchr(rec, ':'); if (! seuser) goto err; seuser++; level = strchr(seuser, ':'); if (! level) goto err; *level = 0; level++; *r_seuser = strdup(seuser); if (! *r_seuser) goto err; len = strlen(level); if (len && level[len-1] == '\n') level[len-1] = 0; *r_level = strdup(level); if (! *r_level) { free(*r_seuser); goto err; } ret = 0; err: free(buffer); if (fp) fclose(fp); free(rec); return (ret ? getseuserbyname(username, r_seuser, r_level) : ret); } libselinux/src/sha1.c0100644 0000000 0000000 00000021617 13756670064 013577 0ustar000000000 0000000 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // LibSha1 // // Implementation of SHA1 hash function. // Original author: Steve Reid // Contributions by: James H. Brown , Saul Kravitz , // and Ralph Giles // Modified by WaterJuice retaining Public Domain license. // // This is free and unencumbered software released into the public domain - June 2013 waterjuice.org // Modified to: // - stop symbols being exported for libselinux shared library - October 2015 // Richard Haines // - Not cast the workspace from a byte array to a CHAR64LONG16 due to allignment isses. // Fixes: // sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align] // CHAR64LONG16* block = (CHAR64LONG16*) workspace; // William Roberts /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // IMPORTS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "sha1.h" #include "dso.h" #include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TYPES /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef union { uint8_t c [64]; uint32_t l [16]; } CHAR64LONG16; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) // blk0() and blk() perform the initial expand. #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |(rol(block->l[i],8)&0x00FF00FF)) #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) // (R0+R1), R2, R3, R4 are the different operations used in SHA1 #define R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); #define R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); #define R2(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); #define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); #define R4(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TransformFunction // // Hash a single 512-bit block. This is the core of the algorithm /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void TransformFunction ( uint32_t state[5], const uint8_t buffer[64] ) { uint32_t a; uint32_t b; uint32_t c; uint32_t d; uint32_t e; CHAR64LONG16 workspace; CHAR64LONG16* block = &workspace; memcpy( block, buffer, 64 ); // Copy context->state[] to working vars a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; // 4 rounds of 20 operations each. Loop unrolled. R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); // Add the working vars back into context.state[] state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Initialise // // Initialises an SHA1 Context. Use this to initialise/reset a context. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void hidden Sha1Initialise ( Sha1Context* Context ) { // SHA1 initialization constants Context->State[0] = 0x67452301; Context->State[1] = 0xEFCDAB89; Context->State[2] = 0x98BADCFE; Context->State[3] = 0x10325476; Context->State[4] = 0xC3D2E1F0; Context->Count[0] = 0; Context->Count[1] = 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Update // // Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on // calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void hidden Sha1Update ( Sha1Context* Context, void* Buffer, uint32_t BufferSize ) { uint32_t i; uint32_t j; j = (Context->Count[0] >> 3) & 63; if( (Context->Count[0] += BufferSize << 3) < (BufferSize << 3) ) { Context->Count[1]++; } Context->Count[1] += (BufferSize >> 29); if( (j + BufferSize) > 63 ) { i = 64 - j; memcpy( &Context->Buffer[j], Buffer, i ); TransformFunction(Context->State, Context->Buffer); for( ; i + 63 < BufferSize; i += 64 ) { TransformFunction(Context->State, (uint8_t*)Buffer + i); } j = 0; } else { i = 0; } memcpy( &Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i ); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Finalise // // Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After // calling this, Sha1Initialised must be used to reuse the context. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void hidden Sha1Finalise ( Sha1Context* Context, SHA1_HASH* Digest ) { uint32_t i; uint8_t finalcount[8]; for( i=0; i<8; i++ ) { finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); // Endian independent } Sha1Update( Context, (uint8_t*)"\x80", 1 ); while( (Context->Count[0] & 504) != 448 ) { Sha1Update( Context, (uint8_t*)"\0", 1 ); } Sha1Update( Context, finalcount, 8 ); // Should cause a Sha1TransformFunction() for( i=0; ibytes[i] = (uint8_t)((Context->State[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } } libselinux/src/sha1.h0100644 0000000 0000000 00000007043 13756670064 013601 0ustar000000000 0000000 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // LibSha1 // // Implementation of SHA1 hash function. // Original author: Steve Reid // Contributions by: James H. Brown , Saul Kravitz , // and Ralph Giles // Modified by WaterJuice retaining Public Domain license. // // This is free and unencumbered software released into the public domain - June 2013 waterjuice.org /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _sha1_h_ #define _sha1_h_ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // IMPORTS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include #include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TYPES /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Context - This must be initialised using Sha1Initialised. Do not modify the contents of this structure directly. typedef struct { uint32_t State[5]; uint32_t Count[2]; uint8_t Buffer[64]; } Sha1Context; #define SHA1_HASH_SIZE ( 160 / 8 ) typedef struct { uint8_t bytes [SHA1_HASH_SIZE]; } SHA1_HASH; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Initialise // // Initialises an SHA1 Context. Use this to initialise/reset a context. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Sha1Initialise ( Sha1Context* Context ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Update // // Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on // calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Sha1Update ( Sha1Context* Context, void* Buffer, uint32_t BufferSize ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sha1Finalise // // Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After // calling this, Sha1Initialised must be used to reuse the context. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Sha1Finalise ( Sha1Context* Context, SHA1_HASH* Digest ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif //_sha1_h_ libselinux/src/stringrep.c0100644 0000000 0000000 00000014624 13756670064 014760 0ustar000000000 0000000 /* * String representation support for classes and permissions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" #define MAXVECTORS 8*sizeof(access_vector_t) struct discover_class_node { char *name; security_class_t value; char **perms; struct discover_class_node *next; }; static struct discover_class_node *discover_class_cache = NULL; static struct discover_class_node * get_class_cache_entry_name(const char *s) { struct discover_class_node *node = discover_class_cache; for (; node != NULL && strcmp(s,node->name) != 0; node = node->next); return node; } static struct discover_class_node * get_class_cache_entry_value(security_class_t c) { struct discover_class_node *node = discover_class_cache; for (; node != NULL && c != node->value; node = node->next); return node; } static struct discover_class_node * discover_class(const char *s) { int fd, ret; char path[PATH_MAX]; char buf[20]; DIR *dir; struct dirent *dentry; size_t i; struct discover_class_node *node; if (!selinux_mnt) { errno = ENOENT; return NULL; } /* allocate a node */ node = malloc(sizeof(struct discover_class_node)); if (node == NULL) return NULL; /* allocate array for perms */ node->perms = calloc(MAXVECTORS,sizeof(char*)); if (node->perms == NULL) goto err1; /* load up the name */ node->name = strdup(s); if (node->name == NULL) goto err2; /* load up class index */ snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) goto err3; memset(buf, 0, sizeof(buf)); ret = read(fd, buf, sizeof(buf) - 1); close(fd); if (ret < 0) goto err3; if (sscanf(buf, "%hu", &node->value) != 1) goto err3; /* load up permission indicies */ snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s); dir = opendir(path); if (dir == NULL) goto err3; dentry = readdir(dir); while (dentry != NULL) { unsigned int value; struct stat m; snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) goto err4; if (fstat(fd, &m) < 0) { close(fd); goto err4; } if (m.st_mode & S_IFDIR) { close(fd); dentry = readdir(dir); continue; } memset(buf, 0, sizeof(buf)); ret = read(fd, buf, sizeof(buf) - 1); close(fd); if (ret < 0) goto err4; if (sscanf(buf, "%u", &value) != 1) goto err4; if (value == 0 || value > MAXVECTORS) goto err4; node->perms[value-1] = strdup(dentry->d_name); if (node->perms[value-1] == NULL) goto err4; dentry = readdir(dir); } closedir(dir); node->next = discover_class_cache; discover_class_cache = node; return node; err4: closedir(dir); for (i=0; iperms[i]); err3: free(node->name); err2: free(node->perms); err1: free(node); return NULL; } hidden void flush_class_cache(void) { struct discover_class_node *cur = discover_class_cache, *prev = NULL; size_t i; while (cur != NULL) { free(cur->name); for (i = 0; i < MAXVECTORS; i++) free(cur->perms[i]); free(cur->perms); prev = cur; cur = cur->next; free(prev); } discover_class_cache = NULL; } security_class_t string_to_security_class(const char *s) { struct discover_class_node *node; node = get_class_cache_entry_name(s); if (node == NULL) { node = discover_class(s); if (node == NULL) { errno = EINVAL; return 0; } } return map_class(node->value); } security_class_t mode_to_security_class(mode_t m) { if (S_ISREG(m)) return string_to_security_class("file"); if (S_ISDIR(m)) return string_to_security_class("dir"); if (S_ISCHR(m)) return string_to_security_class("chr_file"); if (S_ISBLK(m)) return string_to_security_class("blk_file"); if (S_ISFIFO(m)) return string_to_security_class("fifo_file"); if (S_ISLNK(m)) return string_to_security_class("lnk_file"); if (S_ISSOCK(m)) return string_to_security_class("sock_file"); errno=EINVAL; return 0; } access_vector_t string_to_av_perm(security_class_t tclass, const char *s) { struct discover_class_node *node; security_class_t kclass = unmap_class(tclass); node = get_class_cache_entry_value(kclass); if (node != NULL) { size_t i; for (i=0; iperms[i] != NULL; i++) if (strcmp(node->perms[i],s) == 0) return map_perm(tclass, 1<name; } const char *security_av_perm_to_string(security_class_t tclass, access_vector_t av) { struct discover_class_node *node; size_t i; av = unmap_perm(tclass, av); tclass = unmap_class(tclass); node = get_class_cache_entry_value(tclass); if (av && node) for (i = 0; iperms[i]; return NULL; } int security_av_string(security_class_t tclass, access_vector_t av, char **res) { unsigned int i = 0; size_t len = 5; access_vector_t tmp = av; int rc = 0; const char *str; char *ptr; /* first pass computes the required length */ while (tmp) { if (tmp & 1) { str = security_av_perm_to_string(tclass, av & (1<>= 1; i++; } *res = malloc(len); if (!*res) { rc = -1; goto out; } /* second pass constructs the string */ i = 0; tmp = av; ptr = *res; if (!av) { sprintf(ptr, "null"); goto out; } ptr += sprintf(ptr, "{ "); while (tmp) { if (tmp & 1) ptr += sprintf(ptr, "%s ", security_av_perm_to_string( tclass, av & (1<>= 1; i++; } sprintf(ptr, "}"); out: return rc; } void print_access_vector(security_class_t tclass, access_vector_t av) { const char *permstr; access_vector_t bit = 1; if (av == 0) { printf(" null"); return; } printf(" {"); while (av) { if (av & bit) { permstr = security_av_perm_to_string(tclass, bit); if (!permstr) break; printf(" %s", permstr); av &= ~bit; } bit <<= 1; } if (av) printf(" 0x%x", av); printf(" }"); } libselinux/utils/0040755 0000000 0000000 00000000000 13756670064 013144 5ustar000000000 0000000 libselinux/utils/.gitignore0100644 0000000 0000000 00000000612 13756670064 015130 0ustar000000000 0000000 avcstat compute_av compute_create compute_member compute_relabel compute_user getconlist getdefaultcon getenforce getfilecon getpidcon getsebool getseuser matchpathcon policyvers sefcontext_compile selabel_digest selabel_lookup selabel_lookup_best_match selabel_partial_match selinux_check_securetty_context selinuxenabled selinuxexeccon setenforce setfilecon togglesebool selinux_check_access libselinux/utils/Makefile0100644 0000000 0000000 00000005145 13756670064 014606 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr SBINDIR ?= $(PREFIX)/sbin OS ?= $(shell uname) ifeq ($(shell $(CC) -v 2>&1 | grep "clang"),) COMPILER ?= gcc else COMPILER ?= clang endif ifeq ($(COMPILER), gcc) EXTRA_CFLAGS = -fipa-pure-const -Wpacked-bitfield-compat -Wsync-nand -Wcoverage-mismatch \ -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \ -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \ -Wno-suggest-attribute=pure -Wno-suggest-attribute=const endif MAX_STACK_SIZE=8192 CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ -Wunused -Wunknown-pragmas -Wstrict-aliasing -Wshadow -Wpointer-arith \ -Wbad-function-cast -Wcast-align -Wwrite-strings -Waggregate-return \ -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ -Wmissing-declarations -Wmissing-noreturn -Wmissing-format-attribute \ -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wvolatile-register-var \ -Wdisabled-optimization -Wbuiltin-macro-redefined \ -Wattributes -Wmultichar \ -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wendif-labels -Wextra \ -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \ -Woverflow -Wpointer-to-int-cast -Wpragmas \ -Wno-missing-field-initializers -Wno-sign-compare \ -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \ -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \ -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \ -Werror -Wno-aggregate-return -Wno-redundant-decls -Wstrict-overflow=5 \ $(EXTRA_CFLAGS) LD_SONAME_FLAGS=-soname,$(LIBSO),-z,defs,-z,relro ifeq ($(OS), Darwin) override CFLAGS += -I/opt/local/include -I../../libsepol/include override LDFLAGS += -L../../libsepol/src -undefined dynamic_lookup endif override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) override LDFLAGS += -L../src override LDLIBS += -lselinux PCRE_LDLIBS ?= -lpcre ifeq ($(ANDROID_HOST),y) TARGETS=sefcontext_compile else TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c))) endif sefcontext_compile: LDLIBS += $(PCRE_LDLIBS) ../src/libselinux.a -lsepol sefcontext_compile: sefcontext_compile.o ../src/regex.o all: $(TARGETS) install: all -mkdir -p $(DESTDIR)$(SBINDIR) install -m 755 $(TARGETS) $(DESTDIR)$(SBINDIR) clean: rm -f $(TARGETS) *.o *~ distclean: clean indent: ../../scripts/Lindent $(wildcard *.[ch]) relabel: libselinux/utils/avcstat.c0100644 0000000 0000000 00000012452 13756670064 014756 0ustar000000000 0000000 /* * avcstat - Display SELinux avc statistics. * * Copyright (C) 2004 Red Hat, Inc., James Morris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEF_STAT_FILE "/avc/cache_stats" #define DEF_BUF_SIZE 8192 #define HEADERS "lookups hits misses allocations reclaims frees" struct avc_cache_stats { unsigned long long lookups; unsigned long long hits; unsigned long long misses; unsigned long long allocations; unsigned long long reclaims; unsigned long long frees; }; static int interval; static int rows; static char *progname; static char buf[DEF_BUF_SIZE]; /* selinuxfs mount point */ extern char *selinux_mnt; static __attribute__((__format__(printf,1,2),__noreturn__)) void die(const char *msg, ...) { va_list args; fputs("ERROR: ", stderr); va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); if (errno) fprintf(stderr, ": %s", strerror(errno)); fputc('\n', stderr); exit(1); } static void usage(void) { printf("\nUsage: %s [-c] [-f status_file] [interval]\n\n", progname); printf ("Display SELinux AVC statistics. If the interval parameter is specified, the\n"); printf ("program will loop, displaying updated statistics every \'interval\' seconds.\n"); printf ("Relative values are displayed by default. Use the -c option to specify the\n"); printf ("display of cumulative values. The -f option specifies the location of the\n"); printf("AVC statistics file, defaulting to \'%s%s\'.\n\n", selinux_mnt, DEF_STAT_FILE); } static void set_window_rows(void) { int ret; struct winsize ws; ret = ioctl(fileno(stdout), TIOCGWINSZ, &ws); if (ret < 0 || ws.ws_row < 3) ws.ws_row = 24; rows = ws.ws_row; } static void sighandler(int num) { if (num == SIGWINCH) set_window_rows(); } int main(int argc, char **argv) { struct avc_cache_stats tot, rel, last; int fd, i, cumulative = 0; struct sigaction sa; char avcstatfile[PATH_MAX]; snprintf(avcstatfile, sizeof avcstatfile, "%s%s", selinux_mnt, DEF_STAT_FILE); progname = basename(argv[0]); memset(&last, 0, sizeof(last)); while ((i = getopt(argc, argv, "cf:h?-")) != -1) { switch (i) { case 'c': cumulative = 1; break; case 'f': strncpy(avcstatfile, optarg, sizeof(avcstatfile) - 1); avcstatfile[sizeof(avcstatfile)-1] = '\0'; break; case 'h': case '-': usage(); exit(0); default: usage(); die("unrecognized parameter '%c'", i); } } if (optind < argc) { char *arg = argv[optind]; unsigned int n = strtoul(arg, NULL, 10); if (errno == ERANGE) { usage(); die("invalid interval \'%s\'", arg); } if (n == 0) { usage(); exit(0); } interval = n; } sa.sa_handler = sighandler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); i = sigaction(SIGWINCH, &sa, NULL); if (i < 0) die("sigaction"); set_window_rows(); fd = open(avcstatfile, O_RDONLY); if (fd < 0) die("open: \'%s\'", avcstatfile); for (i = 0;; i++) { char *line; ssize_t ret, parsed = 0; memset(buf, 0, DEF_BUF_SIZE); ret = read(fd, buf, DEF_BUF_SIZE-1); if (ret < 0) die("read"); if (ret == 0) die("read: \'%s\': unexpected end of file", avcstatfile); line = strtok(buf, "\n"); if (!line) die("unable to parse \'%s\': end of line not found", avcstatfile); if (strcmp(line, HEADERS)) die("unable to parse \'%s\': invalid headers", avcstatfile); if (!i || !(i % (rows - 2))) printf("%10s %10s %10s %10s %10s %10s\n", "lookups", "hits", "misses", "allocs", "reclaims", "frees"); memset(&tot, 0, sizeof(tot)); while ((line = strtok(NULL, "\n"))) { struct avc_cache_stats tmp; ret = sscanf(line, "%llu %llu %llu %llu %llu %llu", &tmp.lookups, &tmp.hits, &tmp.misses, &tmp.allocations, &tmp.reclaims, &tmp.frees); if (ret != 6) die("unable to parse \'%s\': scan error", avcstatfile); tot.lookups += tmp.lookups; tot.hits += tmp.hits; tot.misses += tmp.misses; tot.allocations += tmp.allocations; tot.reclaims += tmp.reclaims; tot.frees += tmp.frees; parsed = 1; } if (!parsed) die("unable to parse \'%s\': no data", avcstatfile); if (cumulative || !i) printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", tot.lookups, tot.hits, tot.misses, tot.allocations, tot.reclaims, tot.frees); else { rel.lookups = tot.lookups - last.lookups; rel.hits = tot.hits - last.hits; rel.misses = tot.misses - last.misses; rel.allocations = tot.allocations - last.allocations; rel.reclaims = tot.reclaims - last.reclaims; rel.frees = tot.frees - last.frees; printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", rel.lookups, rel.hits, rel.misses, rel.allocations, rel.reclaims, rel.frees); } if (!interval) break; memcpy(&last, &tot, sizeof(last)); sleep(interval); ret = lseek(fd, 0, 0); if (ret < 0) die("lseek"); } close(fd); return 0; } libselinux/utils/compute_av.c0100644 0000000 0000000 00000002057 13756670064 015453 0ustar000000000 0000000 #include #include #include #include #include #include int main(int argc, char **argv) { struct av_decision avd; security_class_t tclass; int ret; if (argc != 4) { fprintf(stderr, "usage: %s scontext tcontext tclass\n", argv[0]); exit(1); } tclass = string_to_security_class(argv[3]); if (!tclass) { fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]); exit(2); } ret = security_compute_av(argv[1], argv[2], tclass, 1, &avd); if (ret < 0) { fprintf(stderr, "%s: security_compute_av failed\n", argv[0]); exit(3); } printf("allowed="); print_access_vector(tclass, avd.allowed); printf("\n"); if (avd.decided != ~0U) { printf("decided="); print_access_vector(tclass, avd.decided); printf("\n"); } if (avd.auditallow) { printf("auditallow="); print_access_vector(tclass, avd.auditallow); printf("\n"); } if (avd.auditdeny != ~0U) { printf("auditdeny"); print_access_vector(tclass, avd.auditdeny); printf("\n"); } exit(0); } libselinux/utils/compute_create.c0100644 0000000 0000000 00000001227 13756670064 016306 0ustar000000000 0000000 #include #include #include #include #include #include int main(int argc, char **argv) { char *buf; security_class_t tclass; int ret; if (argc != 4) { fprintf(stderr, "usage: %s scontext tcontext tclass\n", argv[0]); exit(1); } tclass = string_to_security_class(argv[3]); if (!tclass) { fprintf(stderr, "Invalid class '%s'\n", argv[3]); exit(2); } ret = security_compute_create(argv[1], argv[2], tclass, &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_create failed\n", argv[0]); exit(3); } printf("%s\n", buf); freecon(buf); exit(0); } libselinux/utils/compute_member.c0100644 0000000 0000000 00000001227 13756670064 016312 0ustar000000000 0000000 #include #include #include #include #include #include int main(int argc, char **argv) { char *buf; security_class_t tclass; int ret; if (argc != 4) { fprintf(stderr, "usage: %s scontext tcontext tclass\n", argv[0]); exit(1); } tclass = string_to_security_class(argv[3]); if (!tclass) { fprintf(stderr, "Invalid class '%s'\n", argv[3]); exit(2); } ret = security_compute_member(argv[1], argv[2], tclass, &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_member failed\n", argv[0]); exit(3); } printf("%s\n", buf); freecon(buf); exit(0); } libselinux/utils/compute_relabel.c0100644 0000000 0000000 00000001247 13756670064 016453 0ustar000000000 0000000 #include #include #include #include #include #include int main(int argc, char **argv) { char *buf; security_class_t tclass; int ret; if (argc != 4) { fprintf(stderr, "usage: %s scontext tcontext tclass\n", argv[0]); exit(1); } tclass = string_to_security_class(argv[3]); if (!tclass) { fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]); exit(2); } ret = security_compute_relabel(argv[1], argv[2], tclass, &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_relabel failed\n", argv[0]); exit(3); } printf("%s\n", buf); freecon(buf); exit(0); } libselinux/utils/compute_user.c0100644 0000000 0000000 00000001230 13756670064 016013 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { char **buf, **ptr; int ret; if (argc != 3) { fprintf(stderr, "usage: %s context user\n", argv[0]); exit(1); } ret = security_compute_user(argv[1], argv[2], &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_user(%s,%s) failed\n", argv[0], argv[1], argv[2]); exit(2); } if (!buf[0]) { printf("none\n"); exit(0); } for (ptr = buf; *ptr; ptr++) { printf("%s\n", *ptr); } freeconary(buf); exit(0); } libselinux/utils/getconlist.c0100644 0000000 0000000 00000003153 13756670064 015462 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *name, const char *detail, int rc) { fprintf(stderr, "usage: %s [-l level] user [context]\n", name); if (detail) fprintf(stderr, "%s: %s\n", name, detail); exit(rc); } int main(int argc, char **argv) { char **list, *cur_context = NULL; char *user = NULL, *level = NULL; int ret, i, opt; while ((opt = getopt(argc, argv, "l:")) > 0) { switch (opt) { case 'l': level = strdup(optarg); break; default: usage(argv[0], "invalid option", 1); } } if (((argc - optind) < 1) || ((argc - optind) > 2)) usage(argv[0], "invalid number of arguments", 2); /* If selinux isn't available, bail out. */ if (!is_selinux_enabled()) { fprintf(stderr, "getconlist may be used only on a SELinux kernel.\n"); free(level); return 1; } user = argv[optind]; /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { if (getcon(&cur_context) < 0) { fprintf(stderr, "Couldn't get current context.\n"); free(level); return 2; } } else cur_context = argv[optind + 1]; /* Get the list and print it */ if (level) ret = get_ordered_context_list_with_level(user, level, cur_context, &list); else ret = get_ordered_context_list(user, cur_context, &list); if (ret != -1) { for (i = 0; list[i]; i++) puts(list[i]); freeconary(list); } free(level); return 0; } libselinux/utils/getdefaultcon.c0100644 0000000 0000000 00000004156 13756670064 016137 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *name, const char *detail, int rc) { fprintf(stderr, "usage: %s [-l level] [-s service] user [fromcon]\n", name); if (detail) fprintf(stderr, "%s: %s\n", name, detail); exit(rc); } int main(int argc, char **argv) { char * usercon = NULL, *cur_context = NULL; char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; char *service = NULL; int ret, opt; int verbose = 0; while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) { switch (opt) { case 'l': level = strdup(optarg); break; case 'r': role = strdup(optarg); break; case 's': service = strdup(optarg); break; case 'v': verbose = 1; break; default: usage(argv[0], "invalid option", 1); } } if (((argc - optind) < 1) || ((argc - optind) > 2)) usage(argv[0], "invalid number of arguments", 2); /* If selinux isn't available, bail out. */ if (!is_selinux_enabled()) { fprintf(stderr, "%s may be used only on a SELinux kernel.\n", argv[0]); return 1; } user = argv[optind]; /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { if (getcon(&cur_context) < 0) { fprintf(stderr, "Couldn't get current context.\n"); return 2; } } else cur_context = argv[optind + 1]; if ((ret = getseuser(user, service, &seuser, &dlevel)) == 0) { if (! level) level=dlevel; if (role != NULL && role[0]) ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon); else ret=get_default_context_with_level(seuser, level, cur_context,&usercon); } if (ret < 0) perror(argv[0]); else { if (verbose) { printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); } else { printf("%s\n", usercon); } } free(role); free(seuser); if (level != dlevel) free(level); free(dlevel); free(usercon); return ret >= 0; } libselinux/utils/getenforce.c0100644 0000000 0000000 00000001043 13756670064 015424 0ustar000000000 0000000 #include #include #include #include int main(int argc __attribute__ ((unused)), char **argv __attribute__ ((unused))) { int rc; rc = is_selinux_enabled(); if (rc < 0) { fputs("getenforce: is_selinux_enabled() failed", stderr); return 2; } if (rc == 1) { rc = security_getenforce(); if (rc < 0) { fputs("getenforce: getenforce() failed", stderr); return 2; } if (rc) puts("Enforcing"); else puts("Permissive"); } else { puts("Disabled"); } return 0; } libselinux/utils/getfilecon.c0100644 0000000 0000000 00000000725 13756670064 015430 0ustar000000000 0000000 #include #include #include #include int main(int argc, char **argv) { char *buf; int rc, i; if (argc < 2) { fprintf(stderr, "usage: %s path...\n", argv[0]); exit(1); } for (i = 1; i < argc; i++) { rc = getfilecon(argv[i], &buf); if (rc < 0) { fprintf(stderr, "%s: getfilecon(%s) failed\n", argv[0], argv[i]); exit(2); } printf("%s\t%s\n", argv[i], buf); freecon(buf); } exit(0); } libselinux/utils/getpidcon.c0100644 0000000 0000000 00000001010 13756670064 015251 0ustar000000000 0000000 #include #include #include #include int main(int argc, char **argv) { pid_t pid; char *buf; int rc; if (argc != 2) { fprintf(stderr, "usage: %s pid\n", argv[0]); exit(1); } if (sscanf(argv[1], "%d", &pid) != 1) { fprintf(stderr, "%s: invalid pid %s\n", argv[0], argv[1]); exit(2); } rc = getpidcon(pid, &buf); if (rc < 0) { fprintf(stderr, "%s: getpidcon() failed\n", argv[0]); exit(3); } printf("%s\n", buf); freecon(buf); exit(0); } libselinux/utils/getsebool.c0100644 0000000 0000000 00000004466 13756670064 015302 0ustar000000000 0000000 #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname); exit(1); } int main(int argc, char **argv) { int i, get_all = 0, rc = 0, active, pending, len = 0, opt; char **names = NULL; while ((opt = getopt(argc, argv, "a")) > 0) { switch (opt) { case 'a': if (argc > 2) usage(argv[0]); if (is_selinux_enabled() <= 0) { fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); return 1; } errno = 0; rc = security_get_boolean_names(&names, &len); if (rc) { fprintf(stderr, "%s: Unable to get boolean names: %s\n", argv[0], strerror(errno)); return 1; } if (!len) { printf("No booleans\n"); return 0; } get_all = 1; break; default: usage(argv[0]); } } if (is_selinux_enabled() <= 0) { fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); return 1; } if (!len) { if (argc < 2) usage(argv[0]); len = argc - 1; names = calloc(len, sizeof(char *)); if (!names) { fprintf(stderr, "%s: out of memory\n", argv[0]); return 2; } for (i = 0; i < len; i++) { names[i] = strdup(argv[i + 1]); if (!names[i]) { fprintf(stderr, "%s: out of memory\n", argv[0]); rc = 2; goto out; } } } for (i = 0; i < len; i++) { active = security_get_boolean_active(names[i]); if (active < 0) { if (get_all && errno == EACCES) continue; fprintf(stderr, "Error getting active value for %s\n", names[i]); rc = -1; goto out; } pending = security_get_boolean_pending(names[i]); if (pending < 0) { fprintf(stderr, "Error getting pending value for %s\n", names[i]); rc = -1; goto out; } char *alt_name = selinux_boolean_sub(names[i]); if (! alt_name) { perror("Out of memory\n"); rc = -1; goto out; } if (pending != active) { printf("%s --> %s pending: %s\n", alt_name, (active ? "on" : "off"), (pending ? "on" : "off")); } else { printf("%s --> %s\n", alt_name, (active ? "on" : "off")); } free(alt_name); } out: for (i = 0; i < len; i++) free(names[i]); free(names); return rc; } libselinux/utils/getseuser.c0100644 0000000 0000000 00000001601 13756670064 015311 0ustar000000000 0000000 #include #include #include #include #include #include int main(int argc, char **argv) { char *seuser = NULL, *level = NULL; char **contextlist; int rc, n, i; if (argc != 3) { fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]); exit(1); } rc = getseuserbyname(argv[1], &seuser, &level); if (rc) { fprintf(stderr, "getseuserbyname failed: %s\n", strerror(errno)); exit(2); } printf("seuser: %s, level %s\n", seuser, level); n = get_ordered_context_list_with_level(seuser, level, argv[2], &contextlist); if (n <= 0) { fprintf(stderr, "get_ordered_context_list_with_level failed: %s\n", strerror(errno)); exit(3); } free(seuser); free(level); for (i = 0; i < n; i++) printf("Context %d\t%s\n", i, contextlist[i]); freeconary(contextlist); exit(0); } libselinux/utils/matchpathcon.c0100644 0000000 0000000 00000007400 13756670064 015757 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [-V] [-N] [-n] [-m type] [-f file_contexts_file] [-p prefix] [-P policy_root_path] filepath...\n", progname); exit(1); } static int printmatchpathcon(const char *path, int header, int mode) { char *buf; int rc = matchpathcon(path, mode, &buf); if (rc < 0) { if (errno == ENOENT) { buf=strdup("<>"); } else { fprintf(stderr, "matchpathcon(%s) failed: %s\n", path, strerror(errno)); return 1; } } if (header) printf("%s\t%s\n", path, buf); else printf("%s\n", buf); freecon(buf); return 0; } static mode_t string_to_mode(char *s) { switch (s[0]) { case 'b': return S_IFBLK; case 'c': return S_IFCHR; case 'd': return S_IFDIR; case 'p': return S_IFIFO; case 'l': return S_IFLNK; case 's': return S_IFSOCK; case 'f': return S_IFREG; default: return -1; }; return -1; } int main(int argc, char **argv) { int i, init = 0, force_mode = 0; int header = 1, opt; int verify = 0; int notrans = 0; int error = 0; int quiet = 0; if (argc < 2) usage(argv[0]); while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) { switch (opt) { case 'n': header = 0; break; case 'm': force_mode = string_to_mode(optarg); if (force_mode < 0) { fprintf(stderr, "%s: mode %s is invalid\n", argv[0], optarg); exit(1); } break; case 'V': verify = 1; break; case 'N': notrans = 1; set_matchpathcon_flags(MATCHPATHCON_NOTRANS); break; case 'f': if (init) { fprintf(stderr, "%s: -f and -p are exclusive\n", argv[0]); exit(1); } init = 1; if (matchpathcon_init(optarg)) { fprintf(stderr, "Error while processing %s: %s\n", optarg, errno ? strerror(errno) : "invalid"); exit(1); } break; case 'P': if (selinux_set_policy_root(optarg) < 0 ) { fprintf(stderr, "Error setting policy root %s: %s\n", optarg, errno ? strerror(errno) : "invalid"); exit(1); } break; case 'p': if (init) { fprintf(stderr, "%s: -f and -p are exclusive\n", argv[0]); exit(1); } init = 1; if (matchpathcon_init_prefix(NULL, optarg)) { fprintf(stderr, "Error while processing %s: %s\n", optarg, errno ? strerror(errno) : "invalid"); exit(1); } break; case 'q': quiet = 1; break; default: usage(argv[0]); } } for (i = optind; i < argc; i++) { int rc, mode = 0; struct stat buf; char *path = argv[i]; int len = strlen(path); if (len > 1 && path[len - 1 ] == '/') path[len - 1 ] = '\0'; if (lstat(path, &buf) == 0) mode = buf.st_mode; if (force_mode) mode = force_mode; if (verify) { rc = selinux_file_context_verify(path, mode); if (quiet) { if (rc == 1) continue; else exit(1); } if (rc == -1) { printf("%s error: %s\n", path, strerror(errno)); exit(1); } else if (rc == 1) { printf("%s verified.\n", path); } else { char * con; error = 1; if (notrans) rc = lgetfilecon_raw(path, &con); else rc = lgetfilecon(path, &con); if (rc >= 0) { printf("%s has context %s, should be ", path, con); printmatchpathcon(path, 0, mode); freecon(con); } else { printf ("actual context unknown: %s, should be ", strerror(errno)); printmatchpathcon(path, 0, mode); } } } else { error |= printmatchpathcon(path, header, mode); } } matchpathcon_fini(); return error; } libselinux/utils/policyvers.c0100644 0000000 0000000 00000000464 13756670064 015510 0ustar000000000 0000000 #include #include #include #include int main(int argc __attribute__ ((unused)), char **argv) { int rc; rc = security_policyvers(); if (rc < 0) { fprintf(stderr, "%s: policyvers() failed\n", argv[0]); exit(2); } printf("%d\n", rc); exit(0); } libselinux/utils/sefcontext_compile.c0100644 0000000 0000000 00000027137 13756670064 017211 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include #include "../src/label_file.h" #include "../src/regex.h" const char *policy_file; static int ctx_err; static int validate_context(char **ctxp) { char *ctx = *ctxp; if (policy_file && sepol_check_context(ctx) < 0) { ctx_err = -1; return ctx_err; } return 0; } static int process_file(struct selabel_handle *rec, const char *filename) { unsigned int line_num; int rc; char *line_buf = NULL; size_t line_len = 0; FILE *context_file; const char *prefix = NULL; context_file = fopen(filename, "r"); if (!context_file) { fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno)); return -1; } line_num = 0; rc = 0; while (getline(&line_buf, &line_len, context_file) > 0) { rc = process_line(rec, filename, prefix, line_buf, ++line_num); if (rc || ctx_err) { /* With -p option need to check and fail if ctx err as * process_line() context validation on Linux does not * return an error, but does print the error line to * stderr. Android will set both to error and print * the error line. */ rc = -1; goto out; } } out: free(line_buf); fclose(context_file); return rc; } /* * File Format * * u32 - magic number * u32 - version * u32 - length of pcre version EXCLUDING nul * char - pcre version string EXCLUDING nul * u32 - number of stems * ** Stems * u32 - length of stem EXCLUDING nul * char - stem char array INCLUDING nul * u32 - number of regexs * ** Regexes * u32 - length of upcoming context INCLUDING nul * char - char array of the raw context * u32 - length of the upcoming regex_str * char - char array of the original regex string including the stem. * u32 - mode bits for >= SELINUX_COMPILED_FCONTEXT_MODE * mode_t for <= SELINUX_COMPILED_FCONTEXT_PCRE_VERS * s32 - stemid associated with the regex * u32 - spec has meta characters * u32 - The specs prefix_len if >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN * u32 - data length of the pcre regex * char - a bufer holding the raw pcre regex info * u32 - data length of the pcre regex study daya * char - a buffer holding the raw pcre regex study data */ static int write_binary_file(struct saved_data *data, int fd, int do_write_precompregex) { struct spec *specs = data->spec_arr; FILE *bin_file; size_t len; uint32_t magic = SELINUX_MAGIC_COMPILED_FCONTEXT; uint32_t section_len; uint32_t i; int rc; const char *reg_version; const char *reg_arch; bin_file = fdopen(fd, "w"); if (!bin_file) { perror("fopen output_file"); exit(EXIT_FAILURE); } /* write some magic number */ len = fwrite(&magic, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* write the version */ section_len = SELINUX_COMPILED_FCONTEXT_MAX_VERS; len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* write version of the regex back-end */ reg_version = regex_version(); if (!reg_version) goto err; section_len = strlen(reg_version); len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; len = fwrite(reg_version, sizeof(char), section_len, bin_file); if (len != section_len) goto err; /* write regex arch string */ reg_arch = regex_arch_string(); if (!reg_arch) goto err; section_len = strlen(reg_arch); len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; len = fwrite(reg_arch, sizeof(char), section_len, bin_file); if (len != section_len) goto err; /* write the number of stems coming */ section_len = data->num_stems; len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; for (i = 0; i < section_len; i++) { char *stem = data->stem_arr[i].buf; uint32_t stem_len = data->stem_arr[i].len; /* write the strlen (aka no nul) */ len = fwrite(&stem_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* include the nul in the file */ stem_len += 1; len = fwrite(stem, sizeof(char), stem_len, bin_file); if (len != stem_len) goto err; } /* write the number of regexes coming */ section_len = data->nspec; len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; for (i = 0; i < section_len; i++) { char *context = specs[i].lr.ctx_raw; char *regex_str = specs[i].regex_str; mode_t mode = specs[i].mode; size_t prefix_len = specs[i].prefix_len; int32_t stem_id = specs[i].stem_id; struct regex_data *re = specs[i].regex; uint32_t to_write; /* length of the context string (including nul) */ to_write = strlen(context) + 1; len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* original context strin (including nul) */ len = fwrite(context, sizeof(char), to_write, bin_file); if (len != to_write) goto err; /* length of the original regex string (including nul) */ to_write = strlen(regex_str) + 1; len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* original regex string */ len = fwrite(regex_str, sizeof(char), to_write, bin_file); if (len != to_write) goto err; /* binary F_MODE bits */ to_write = mode; len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); if (len != 1) goto err; /* stem for this regex (could be -1) */ len = fwrite(&stem_id, sizeof(stem_id), 1, bin_file); if (len != 1) goto err; /* does this spec have a metaChar? */ to_write = specs[i].hasMetaChars; len = fwrite(&to_write, sizeof(to_write), 1, bin_file); if (len != 1) goto err; /* For SELINUX_COMPILED_FCONTEXT_PREFIX_LEN */ to_write = prefix_len; len = fwrite(&to_write, sizeof(to_write), 1, bin_file); if (len != 1) goto err; /* Write regex related data */ rc = regex_writef(re, bin_file, do_write_precompregex); if (rc < 0) goto err; } rc = 0; out: fclose(bin_file); return rc; err: rc = -1; goto out; } static void free_specs(struct saved_data *data) { struct spec *specs = data->spec_arr; unsigned int num_entries = data->nspec; unsigned int i; for (i = 0; i < num_entries; i++) { free(specs[i].lr.ctx_raw); free(specs[i].lr.ctx_trans); free(specs[i].regex_str); free(specs[i].type_str); regex_data_free(specs[i].regex); } free(specs); num_entries = data->num_stems; for (i = 0; i < num_entries; i++) free(data->stem_arr[i].buf); free(data->stem_arr); memset(data, 0, sizeof(*data)); } static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [-o out_file] [-p policy_file] fc_file\n" "Where:\n\t" "-o Optional file name of the PCRE formatted binary\n\t" " file to be output. If not specified the default\n\t" " will be fc_file with the .bin suffix appended.\n\t" "-p Optional binary policy file that will be used to\n\t" " validate contexts defined in the fc_file.\n\t" "-r Omit precompiled regular expressions from the output.\n\t" " (PCRE2 only. Compiled PCRE2 regular expressions are\n\t" " not portable across architectures. Use this flag\n\t" " if you know that you build for an incompatible\n\t" " architecture to save space. When linked against\n\t" " PCRE1 this flag is ignored.)\n\t" "-i Print regular expression info end exit. That is, back\n\t" " end version and architecture identifier.\n\t" " Arch identifier format (PCRE2):\n\t" " --, e.g.,\n\t" " \"8-8-el\" for x86_64.\n\t" "fc_file The text based file contexts file to be processed.\n", progname); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { const char *path = NULL; const char *out_file = NULL; int do_write_precompregex = 1; char stack_path[PATH_MAX + 1]; char *tmp = NULL; int fd, rc, opt; FILE *policy_fp = NULL; struct stat buf; struct selabel_handle *rec = NULL; struct saved_data *data = NULL; if (argc < 2) usage(argv[0]); while ((opt = getopt(argc, argv, "io:p:r")) > 0) { switch (opt) { case 'o': out_file = optarg; break; case 'p': policy_file = optarg; break; case 'r': do_write_precompregex = 0; break; case 'i': printf("%s (%s)\n", regex_version(), regex_arch_string()); return 0; default: usage(argv[0]); } } if (optind >= argc) usage(argv[0]); path = argv[optind]; if (stat(path, &buf) < 0) { fprintf(stderr, "%s: could not stat: %s: %s\n", argv[0], path, strerror(errno)); exit(EXIT_FAILURE); } /* Open binary policy if supplied. */ if (policy_file) { policy_fp = fopen(policy_file, "r"); if (!policy_fp) { fprintf(stderr, "%s: failed to open %s: %s\n", argv[0], policy_file, strerror(errno)); exit(EXIT_FAILURE); } if (sepol_set_policydb_from_file(policy_fp) < 0) { fprintf(stderr, "%s: failed to load policy from %s\n", argv[0], policy_file); fclose(policy_fp); exit(EXIT_FAILURE); } } /* Generate dummy handle for process_line() function */ rec = (struct selabel_handle *)calloc(1, sizeof(*rec)); if (!rec) { fprintf(stderr, "%s: calloc failed: %s\n", argv[0], strerror(errno)); if (policy_fp) fclose(policy_fp); exit(EXIT_FAILURE); } rec->backend = SELABEL_CTX_FILE; /* Need to set validation on to get the bin file generated by the * process_line function, however as the bin file being generated * may not be related to the currently loaded policy (that it * would be validated against), then set callback to ignore any * validation - unless the -p option is used in which case if an * error is detected, the process will be aborted. */ rec->validating = 1; selinux_set_callback(SELINUX_CB_VALIDATE, (union selinux_callback)&validate_context); data = (struct saved_data *)calloc(1, sizeof(*data)); if (!data) { fprintf(stderr, "%s: calloc failed: %s\n", argv[0], strerror(errno)); free(rec); if (policy_fp) fclose(policy_fp); exit(EXIT_FAILURE); } rec->data = data; rc = process_file(rec, path); if (rc < 0) { fprintf(stderr, "%s: process_file failed\n", argv[0]); goto err; } rc = sort_specs(data); if (rc) { fprintf(stderr, "%s: sort_specs failed\n", argv[0]); goto err; } if (out_file) rc = snprintf(stack_path, sizeof(stack_path), "%s", out_file); else rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path); if (rc < 0 || rc >= (int)sizeof(stack_path)) { fprintf(stderr, "%s: snprintf failed\n", argv[0]); goto err; } tmp = malloc(strlen(stack_path) + 7); if (!tmp) { fprintf(stderr, "%s: malloc failed: %s\n", argv[0], strerror(errno)); goto err; } rc = sprintf(tmp, "%sXXXXXX", stack_path); if (rc < 0) { fprintf(stderr, "%s: sprintf failed\n", argv[0]); goto err; } fd = mkstemp(tmp); if (fd < 0) { fprintf(stderr, "%s: mkstemp %s failed: %s\n", argv[0], tmp, strerror(errno)); goto err; } rc = fchmod(fd, buf.st_mode); if (rc < 0) { fprintf(stderr, "%s: fchmod %s failed: %s\n", argv[0], tmp, strerror(errno)); goto err_unlink; } rc = write_binary_file(data, fd, do_write_precompregex); if (rc < 0) { fprintf(stderr, "%s: write_binary_file %s failed\n", argv[0], tmp); goto err_unlink; } rc = rename(tmp, stack_path); if (rc < 0) { fprintf(stderr, "%s: rename %s -> %s failed: %s\n", argv[0], tmp, stack_path, strerror(errno)); goto err_unlink; } rc = 0; out: if (policy_fp) fclose(policy_fp); free_specs(data); free(rec); free(data); free(tmp); return rc; err_unlink: unlink(tmp); err: rc = -1; goto out; } libselinux/utils/selabel_digest.c0100644 0000000 0000000 00000010527 13756670064 016260 0ustar000000000 0000000 #include #include #include #include #include #include #include static size_t digest_len; static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s -b backend [-d] [-v] [-B] [-i] [-f file]\n\n" "Where:\n\t" "-b The backend - \"file\", \"media\", \"x\", \"db\" or " "\"prop\"\n\t" "-v Run \"cat | openssl dgst -sha1 -hex\"\n\t" " on the list of specfiles to compare the SHA1 digests.\n\t" "-B Use base specfiles only (valid for \"-b file\" only).\n\t" "-i Do not request a digest.\n\t" "-f Optional file containing the specs (defaults to\n\t" " those used by loaded policy).\n\n", progname); exit(1); } static int run_check_digest(char *cmd, char *selabel_digest) { FILE *fp; char files_digest[128]; char *files_ptr; int rc = 0; fp = popen(cmd, "r"); if (!fp) { printf("Failed to run command line\n"); return -1; } /* Only expect one line "(stdin)= x.." so read and find first space */ while (fgets(files_digest, sizeof(files_digest) - 1, fp) != NULL) ; files_ptr = strstr(files_digest, " "); rc = strncmp(selabel_digest, files_ptr + 1, digest_len * 2); if (rc) { printf("Failed validation:\n\tselabel_digest: %s\n\t" "files_digest: %s\n", selabel_digest, files_ptr + 1); } else { printf("Passed validation - digest: %s\n", selabel_digest); } pclose(fp); return rc; } int main(int argc, char **argv) { int backend = 0, rc, opt, validate = 0; char *baseonly = NULL, *file = NULL, *digest = (char *)1; char **specfiles = NULL; unsigned char *sha1_digest = NULL; size_t i, num_specfiles; char cmd_buf[4096]; char *cmd_ptr; char *sha1_buf; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { { SELABEL_OPT_PATH, file }, { SELABEL_OPT_BASEONLY, baseonly }, { SELABEL_OPT_DIGEST, digest } }; if (argc < 3) usage(argv[0]); while ((opt = getopt(argc, argv, "ib:Bvf:")) > 0) { switch (opt) { case 'b': if (!strcasecmp(optarg, "file")) { backend = SELABEL_CTX_FILE; } else if (!strcmp(optarg, "media")) { backend = SELABEL_CTX_MEDIA; } else if (!strcmp(optarg, "x")) { backend = SELABEL_CTX_X; } else if (!strcmp(optarg, "db")) { backend = SELABEL_CTX_DB; } else if (!strcmp(optarg, "prop")) { backend = SELABEL_CTX_ANDROID_PROP; } else if (!strcmp(optarg, "service")) { backend = SELABEL_CTX_ANDROID_SERVICE; } else { fprintf(stderr, "Unknown backend: %s\n", optarg); usage(argv[0]); } break; case 'B': baseonly = (char *)1; break; case 'v': validate = 1; break; case 'i': digest = NULL; break; case 'f': file = optarg; break; default: usage(argv[0]); } } memset(cmd_buf, 0, sizeof(cmd_buf)); selabel_option[0].value = file; selabel_option[1].value = baseonly; selabel_option[2].value = digest; hnd = selabel_open(backend, selabel_option, 3); if (!hnd) { switch (errno) { case EOVERFLOW: fprintf(stderr, "ERROR Number of specfiles or specfile" " buffer caused an overflow.\n"); break; default: fprintf(stderr, "ERROR: selabel_open: %s\n", strerror(errno)); } return -1; } rc = selabel_digest(hnd, &sha1_digest, &digest_len, &specfiles, &num_specfiles); if (rc) { switch (errno) { case EINVAL: fprintf(stderr, "No digest available.\n"); break; default: fprintf(stderr, "selabel_digest ERROR: %s\n", strerror(errno)); } goto err; } sha1_buf = malloc(digest_len * 2 + 1); if (!sha1_buf) { fprintf(stderr, "Could not malloc buffer ERROR: %s\n", strerror(errno)); rc = -1; goto err; } printf("SHA1 digest: "); for (i = 0; i < digest_len; i++) sprintf(&(sha1_buf[i * 2]), "%02x", sha1_digest[i]); printf("%s\n", sha1_buf); printf("calculated using the following specfile(s):\n"); if (specfiles) { cmd_ptr = &cmd_buf[0]; sprintf(cmd_ptr, "/usr/bin/cat "); cmd_ptr = &cmd_buf[0] + strlen(cmd_buf); for (i = 0; i < num_specfiles; i++) { sprintf(cmd_ptr, "%s ", specfiles[i]); cmd_ptr += strlen(specfiles[i]) + 1; printf("%s\n", specfiles[i]); } sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex"); if (validate) rc = run_check_digest(cmd_buf, sha1_buf); } free(sha1_buf); err: selabel_close(hnd); return rc; } libselinux/utils/selabel_lookup.c0100644 0000000 0000000 00000006144 13756670064 016312 0ustar000000000 0000000 #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s -b backend [-v] [-r] -k key [-t type] [-f file]\n\n" "Where:\n\t" "-b The backend - \"file\", \"media\", \"x\", \"db\" or " "\"prop\"\n\t" "-v Validate entries against loaded policy.\n\t" "-r Use \"raw\" function.\n\t" "-k Lookup key - Depends on backend.\n\t" "-t Lookup type - Optional as depends on backend.\n\t" "-f Optional file containing the specs (defaults to\n\t" " those used by loaded policy).\n\n" "Examples:\n\t" "%s -v -b file -k /run -t 0\n\t" " lookup with validation against the loaded policy, the\n\t" " \"file\" backend for path \"/run\" with mode = 0\n\t" "%s -r -b x -t 4 -k X11:ButtonPress\n\t" " lookup_raw the \"X\" backend for type SELABEL_X_EVENT\n\t" " using key \"X11:ButtonPress\"\n\n", progname, progname, progname); exit(1); } int main(int argc, char **argv) { int raw = 0, type = 0, backend = 0, rc, opt; char *validate = NULL, *key = NULL, *context = NULL, *file = NULL; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { { SELABEL_OPT_PATH, file }, { SELABEL_OPT_VALIDATE, validate } }; if (argc < 3) usage(argv[0]); while ((opt = getopt(argc, argv, "b:f:vrk:t:")) > 0) { switch (opt) { case 'b': if (!strcasecmp(optarg, "file")) { backend = SELABEL_CTX_FILE; } else if (!strcmp(optarg, "media")) { backend = SELABEL_CTX_MEDIA; } else if (!strcmp(optarg, "x")) { backend = SELABEL_CTX_X; } else if (!strcmp(optarg, "db")) { backend = SELABEL_CTX_DB; } else if (!strcmp(optarg, "prop")) { backend = SELABEL_CTX_ANDROID_PROP; } else if (!strcmp(optarg, "service")) { backend = SELABEL_CTX_ANDROID_SERVICE; } else { fprintf(stderr, "Unknown backend: %s\n", optarg); usage(argv[0]); } break; case 'f': file = optarg; break; case 'v': validate = (char *)1; break; case 'r': raw = 1; break; case 'k': key = optarg; break; case 't': type = atoi(optarg); break; default: usage(argv[0]); } } selabel_option[0].value = file; selabel_option[1].value = validate; hnd = selabel_open(backend, selabel_option, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " "handle.\n"); return -1; } switch (raw) { case 1: rc = selabel_lookup_raw(hnd, &context, key, type); break; default: rc = selabel_lookup(hnd, &context, key, type); } selabel_close(hnd); if (rc) { switch (errno) { case ENOENT: fprintf(stderr, "ERROR: selabel_lookup failed to " "find a valid context.\n"); break; case EINVAL: fprintf(stderr, "ERROR: selabel_lookup failed to " "validate context, or key / type are " "invalid.\n"); break; default: fprintf(stderr, "selabel_lookup ERROR: %s\n", strerror(errno)); } } else { printf("Default context: %s\n", context); freecon(context); } return rc; } libselinux/utils/selabel_lookup_best_match.c0100644 0000000 0000000 00000007173 13756670064 020506 0ustar000000000 0000000 #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [-v] [-r] -p path [-m mode] [-f file] [link...]\n\n" "Where:\n\t" "-v Validate file_contxts entries against loaded policy.\n\t" "-r Use \"raw\" function.\n\t" "-p Path to check for best match using the link(s) provided.\n\t" "-m Optional mode (b, c, d, p, l, s or f) Defaults to 0.\n\t" "-f Optional file containing the specs (defaults to\n\t" " those used by loaded policy).\n\t" "link Zero or more links to check against, the order of\n\t" " precedence for best match is:\n\t\t" " 1) An exact match for the real path (if no links), or\n\t\t" " 2) An exact match for any of the links (aliases), or\n\t\t" " 3) The longest fixed prefix match.\n\n" "Example:\n\t" "%s -p /dev/initctl /run/systemd/initctl/fifo\n\t" " Find best matching context for the specified path using one link.\n\n", progname, progname); exit(1); } static mode_t string_to_mode(char *s) { switch (s[0]) { case 'b': return S_IFBLK; case 'c': return S_IFCHR; case 'd': return S_IFDIR; case 'p': return S_IFIFO; case 'l': return S_IFLNK; case 's': return S_IFSOCK; case 'f': return S_IFREG; }; return 0; } int main(int argc, char **argv) { int raw = 0, mode = 0, rc, opt, i, num_links, string_len; char *validate = NULL, *path = NULL, *context = NULL, *file = NULL; char **links = NULL; struct selabel_handle *hnd; struct selinux_opt options[] = { { SELABEL_OPT_PATH, file }, { SELABEL_OPT_VALIDATE, validate } }; if (argc < 3) usage(argv[0]); while ((opt = getopt(argc, argv, "f:vrp:m:")) > 0) { switch (opt) { case 'f': file = optarg; break; case 'v': validate = (char *)1; break; case 'r': raw = 1; break; case 'p': path = optarg; break; case 'm': mode = string_to_mode(optarg); break; default: usage(argv[0]); } } /* Count links */ for (i = optind, num_links = 0; i < argc; i++, num_links++) ; if (num_links) { links = calloc(num_links + 1, sizeof(char *)); if (!links) { fprintf(stderr, "ERROR: calloc failed.\n"); exit(1); } for (i = optind, num_links = 0; i < argc; i++, num_links++) { string_len = strlen(argv[i]) + 1; links[num_links] = malloc(string_len); if (!links[num_links]) { fprintf(stderr, "ERROR: malloc failed.\n"); exit(1); } strcpy(links[num_links], argv[i]); } } options[0].value = file; options[1].value = validate; hnd = selabel_open(SELABEL_CTX_FILE, options, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " "handle.\n"); rc = -1; goto out; } if (raw) rc = selabel_lookup_best_match_raw(hnd, &context, path, (const char **)links, mode); else rc = selabel_lookup_best_match(hnd, &context, path, (const char **)links, mode); selabel_close(hnd); if (rc) { switch (errno) { case ENOENT: fprintf(stderr, "ERROR: selabel_lookup_best_match " "failed to find a valid context.\n"); break; case EINVAL: fprintf(stderr, "ERROR: selabel_lookup_best_match " "failed to validate context, or path / mode " "are invalid.\n"); break; default: fprintf(stderr, "selabel_lookup_best_match ERROR: " "%s\n", strerror(errno)); } } else { printf("Best match context: %s\n", context); freecon(context); } out: if (links) { for (i = 0; links[i]; i++) free(links[i]); free(links); } return rc; } libselinux/utils/selabel_partial_match.c0100644 0000000 0000000 00000003406 13756670064 017607 0ustar000000000 0000000 #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [-v] -p [-f file]\n\n" "Where:\n\t" "-v Validate file_contxts entries against loaded policy.\n\t" "-p Path to check if a match or partial match is possible\n\t" " against a regex entry in the file_contexts file.\n\t" "-f Optional file_contexts file (defaults to current policy).\n\n" "Example:\n\t" "%s -p /sys/devices/system/cpu/online\n\t" " Check if a match or partial match is possible against\n\t" " the path \"/sys/devices/system/cpu/online\", returning\n\t" " TRUE or FALSE.\n\n", progname, progname); exit(1); } int main(int argc, char **argv) { int opt; bool partial_match; char *validate = NULL, *path = NULL, *file = NULL; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { { SELABEL_OPT_PATH, file }, { SELABEL_OPT_VALIDATE, validate } }; if (argc < 2) usage(argv[0]); while ((opt = getopt(argc, argv, "f:vp:")) > 0) { switch (opt) { case 'f': file = optarg; break; case 'v': validate = (char *)1; break; case 'p': path = optarg; break; default: usage(argv[0]); } } selabel_option[0].value = file; selabel_option[1].value = validate; hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " "handle.\n"); return -1; } partial_match = selabel_partial_match(hnd, path); printf("Match or Partial match: %s\n", partial_match == 1 ? "TRUE" : "FALSE"); selabel_close(hnd); return partial_match; } libselinux/utils/selinux_check_access.c0100644 0000000 0000000 00000002115 13756670064 017451 0ustar000000000 0000000 #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [-a auditdata] scon tcon class perm\n" "\nWhere:\n\t" "-a Optional information added to audit message.\n", progname); exit(1); } static int cb_auditinfo(void *auditdata, __attribute__((unused))security_class_t class, char *msgbuf, size_t msgbufsize) { return snprintf(msgbuf, msgbufsize, "%s", (char *)auditdata); } int main(int argc, char **argv) { int opt, rc; char *audit_msg = NULL; while ((opt = getopt(argc, argv, "a:")) != -1) { switch (opt) { case 'a': audit_msg = optarg; break; default: usage(argv[0]); } } if ((argc - optind) != 4) usage(argv[0]); if (audit_msg) selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)cb_auditinfo); rc = selinux_check_access(argv[optind], argv[optind + 1], argv[optind + 2], argv[optind + 3], audit_msg); if (rc < 0) perror("selinux_check_access"); return rc; } libselinux/utils/selinux_check_securetty_context.c0100644 0000000 0000000 00000001224 13756670064 022003 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s tty_context...\n", progname); exit(1); } int main(int argc, char **argv) { int i; if (argc < 2) usage(argv[0]); for (i = 1; i < argc; i++) { switch (selinux_check_securetty_context(argv[i])) { case 0: printf("%s securetty.\n", argv[i]); break; default: printf("%s not securetty.\n", argv[i]); break; } } return 0; } libselinux/utils/selinuxenabled.c0100644 0000000 0000000 00000000213 13756670064 016303 0ustar000000000 0000000 #include #include #include #include int main(void) { return !is_selinux_enabled(); } libselinux/utils/selinuxexeccon.c0100644 0000000 0000000 00000002311 13756670064 016336 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *name, const char *detail, int rc) { fprintf(stderr, "usage: %s command [ fromcon ]\n", name); if (detail) fprintf(stderr, "%s: %s\n", name, detail); exit(rc); } static char * get_selinux_proc_context(const char *command, char * execcon) { char * fcon = NULL, *newcon = NULL; int ret = getfilecon(command, &fcon); if (ret < 0) goto err; ret = security_compute_create(execcon, fcon, string_to_security_class("process"), &newcon); if (ret < 0) goto err; err: freecon(fcon); return newcon; } int main(int argc, char **argv) { int ret = -1; char * proccon = NULL, *con = NULL; if (argc < 2 || argc > 3) usage(argv[0], "Invalid number of arguments", -1); if (argc == 2) { if (getcon(&con) < 0) { perror(argv[0]); return -1; } } else { con = strdup(argv[2]); } proccon = get_selinux_proc_context(argv[1], con); if (proccon) { printf("%s\n", proccon); ret = 0; } else { perror(argv[0]); } free(proccon); free(con); return ret; } libselinux/utils/setenforce.c0100644 0000000 0000000 00000001645 13756670064 015450 0ustar000000000 0000000 #include #include #include #include #include #include #include static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s [ Enforcing | Permissive | 1 | 0 ]\n", progname); exit(1); } int main(int argc, char **argv) { int rc = 0; if (argc != 2) { usage(argv[0]); } if (is_selinux_enabled() <= 0) { fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); return 1; } if (strlen(argv[1]) == 1 && (argv[1][0] == '0' || argv[1][0] == '1')) { rc = security_setenforce(atoi(argv[1])); } else { if (strcasecmp(argv[1], "enforcing") == 0) { rc = security_setenforce(1); } else if (strcasecmp(argv[1], "permissive") == 0) { rc = security_setenforce(0); } else usage(argv[0]); } if (rc < 0) { fprintf(stderr, "%s: setenforce() failed\n", argv[0]); return 2; } return 0; } libselinux/utils/setfilecon.c0100644 0000000 0000000 00000000654 13756670064 015445 0ustar000000000 0000000 #include #include #include #include int main(int argc, char **argv) { int rc, i; if (argc < 3) { fprintf(stderr, "usage: %s context path...\n", argv[0]); exit(1); } for (i = 2; i < argc; i++) { rc = setfilecon(argv[i], argv[1]); if (rc < 0) { fprintf(stderr, "%s: setfilecon(%s,%s) failed\n", argv[0], argv[i], argv[1]); exit(2); } } exit(0); } libselinux/utils/togglesebool.c0100644 0000000 0000000 00000004214 13756670064 015773 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include /* Attempt to rollback the transaction. No need to check error codes since this is rolling back something that blew up. */ static __attribute__ ((__noreturn__)) void rollback(int argc, char **argv) { int i; for (i = 1; i < argc; i++) security_set_boolean(argv[i], security_get_boolean_active(argv[i])); exit(1); } int main(int argc, char **argv) { int rc, i, commit = 0; if (is_selinux_enabled() <= 0) { fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); return 1; } if (argc < 2) { printf("Usage: %s boolname1 [boolname2 ...]\n", basename(argv[0])); return 1; } for (i = 1; i < argc; i++) { printf("%s: ", argv[i]); rc = security_get_boolean_active(argv[i]); switch (rc) { case 1: if (security_set_boolean(argv[i], 0) >= 0) { printf("inactive\n"); commit++; } else { printf("%s - rolling back all changes\n", strerror(errno)); rollback(i, argv); } break; case 0: if (security_set_boolean(argv[i], 1) >= 0) { printf("active\n"); commit++; } else { printf("%s - rolling back all changes\n", strerror(errno)); rollback(i, argv); } break; default: if (errno == ENOENT) printf ("Boolean does not exist - rolling back all changes.\n"); else printf("%s - rolling back all changes.\n", strerror(errno)); rollback(i, argv); break; /* Not reached. */ } } if (commit > 0) { if (security_commit_booleans() < 0) { printf("Commit failed. (%s) No change to booleans.\n", strerror(errno)); } else { /* syslog all the changes */ struct passwd *pwd = getpwuid(getuid()); for (i = 1; i < argc; i++) { if (pwd && pwd->pw_name) syslog(LOG_NOTICE, "The %s policy boolean was toggled by %s", argv[i], pwd->pw_name); else syslog(LOG_NOTICE, "The %s policy boolean was toggled by uid:%u", argv[i], getuid()); } return 0; } } return 1; } libsemanage/0040755 0000000 0000000 00000000000 13756670064 012075 5ustar000000000 0000000 libsemanage/.gitignore0100644 0000000 0000000 00000000062 13756670064 014060 0ustar000000000 0000000 src/conf-parse.c src/conf-parse.h src/conf-scan.c libsemanage/COPYING0100644 0000000 0000000 00000063500 13756670064 013131 0ustar000000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, 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. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libsemanage/Makefile0100644 0000000 0000000 00000001010 13756670064 013522 0ustar000000000 0000000 all: $(MAKE) -C src all swigify: $(MAKE) -C src swigify pywrap: $(MAKE) -C src pywrap rubywrap: $(MAKE) -C src rubywrap install: $(MAKE) -C include install $(MAKE) -C src install $(MAKE) -C man install $(MAKE) -C utils install install-pywrap: $(MAKE) -C src install-pywrap install-rubywrap: $(MAKE) -C src install-rubywrap relabel: $(MAKE) -C src relabel clean distclean: $(MAKE) -C src $@ $(MAKE) -C tests $@ indent: $(MAKE) -C src $@ $(MAKE) -C include $@ test: all $(MAKE) -C tests test libsemanage/VERSION0100644 0000000 0000000 00000000004 13756670064 013134 0ustar000000000 0000000 2.9 libsemanage/example/0040755 0000000 0000000 00000000000 13756670064 013530 5ustar000000000 0000000 libsemanage/example/test_fcontext.c0100644 0000000 0000000 00000003475 13756670064 016573 0ustar000000000 0000000 #include #include #include #include #include #include #include int main(const int argc, const char **argv) { semanage_handle_t *sh = NULL; semanage_fcontext_t *fcontext; semanage_context_t *con; semanage_fcontext_key_t *k; int exist = 0; sh = semanage_handle_create(); if (sh == NULL) { perror("Can't create semanage handle\n"); return -1; } if (semanage_access_check(sh) < 0) { perror("Semanage access check failed\n"); return -1; } if (semanage_connect(sh) < 0) { perror("Semanage connect failed\n"); return -1; } if (semanage_fcontext_key_create(sh, argv[2], SEMANAGE_FCONTEXT_REG, &k) < 0) { fprintf(stderr, "Could not create key for %s", argv[2]); return -1; } if(semanage_fcontext_exists(sh, k, &exist) < 0) { fprintf(stderr,"Could not check if key exists for %s", argv[2]); return -1; } if (exist) { fprintf(stderr,"Could create %s mapping already exists", argv[2]); return -1; } if (semanage_fcontext_create(sh, &fcontext) < 0) { fprintf(stderr,"Could not create file context for %s", argv[2]); return -1; } semanage_fcontext_set_expr(sh, fcontext, argv[2]); if (semanage_context_from_string(sh, argv[1], &con)) { fprintf(stderr,"Could not create context using %s for file context %s", argv[1], argv[2]); return -1; } if (semanage_fcontext_set_con(sh, fcontext, con) < 0) { fprintf(stderr,"Could not set file context for %s", argv[2]); return -1; } semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_REG); if(semanage_fcontext_modify_local(sh, k, fcontext) < 0) { fprintf(stderr,"Could not add file context for %s", argv[2]); return -1; } semanage_fcontext_key_free(k); semanage_fcontext_free(fcontext); return 0; } libsemanage/include/0040755 0000000 0000000 00000000000 13756670064 013520 5ustar000000000 0000000 libsemanage/include/Makefile0100644 0000000 0000000 00000000440 13756670064 015153 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr INCDIR ?= $(PREFIX)/include/semanage all: install: all test -d $(DESTDIR)$(INCDIR) || install -m 755 -d $(DESTDIR)$(INCDIR) install -m 644 $(wildcard semanage/*.h) $(DESTDIR)$(INCDIR) indent: ../../scripts/Lindent $(wildcard semanage/*.h) libsemanage/include/semanage/0040755 0000000 0000000 00000000000 13756670064 015300 5ustar000000000 0000000 libsemanage/include/semanage/boolean_record.h0100644 0000000 0000000 00000003123 13756670064 020422 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_BOOLEAN_RECORD_H_ #define _SEMANAGE_BOOLEAN_RECORD_H_ #include #ifndef _SEMANAGE_BOOL_DEFINED_ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool semanage_bool_t; typedef struct semanage_bool_key semanage_bool_key_t; #define _SEMANAGE_BOOL_DEFINED_ #endif /* Key */ extern int semanage_bool_key_create(semanage_handle_t * handle, const char *name, semanage_bool_key_t ** key); extern int semanage_bool_key_extract(semanage_handle_t * handle, const semanage_bool_t * boolean, semanage_bool_key_t ** key); extern void semanage_bool_key_free(semanage_bool_key_t * key); extern int semanage_bool_compare(const semanage_bool_t * boolean, const semanage_bool_key_t * key); extern int semanage_bool_compare2(const semanage_bool_t * boolean, const semanage_bool_t * boolean2); /* Name */ extern const char *semanage_bool_get_name(const semanage_bool_t * boolean); extern int semanage_bool_set_name(semanage_handle_t * handle, semanage_bool_t * boolean, const char *name); /* Value */ extern int semanage_bool_get_value(const semanage_bool_t * boolean); extern void semanage_bool_set_value(semanage_bool_t * boolean, int value); /* Create/Clone/Destroy */ extern int semanage_bool_create(semanage_handle_t * handle, semanage_bool_t ** bool_ptr); extern int semanage_bool_clone(semanage_handle_t * handle, const semanage_bool_t * boolean, semanage_bool_t ** bool_ptr); extern void semanage_bool_free(semanage_bool_t * boolean); #endif libsemanage/include/semanage/booleans_active.h0100644 0000000 0000000 00000002003 13756670064 020576 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_BOOLEANS_ACTIVE_H_ #define _SEMANAGE_BOOLEANS_ACTIVE_H_ #include #include extern int semanage_bool_set_active(semanage_handle_t * handle, const semanage_bool_key_t * key, const semanage_bool_t * data); extern int semanage_bool_query_active(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response); extern int semanage_bool_exists_active(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response); extern int semanage_bool_count_active(semanage_handle_t * handle, unsigned int *response); extern int semanage_bool_iterate_active(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg); extern int semanage_bool_list_active(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count); #endif libsemanage/include/semanage/booleans_local.h0100644 0000000 0000000 00000002166 13756670064 020427 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_BOOLEANS_LOCAL_H_ #define _SEMANAGE_BOOLEANS_LOCAL_H_ #include #include extern int semanage_bool_modify_local(semanage_handle_t * handle, const semanage_bool_key_t * key, const semanage_bool_t * data); extern int semanage_bool_del_local(semanage_handle_t * handle, const semanage_bool_key_t * key); extern int semanage_bool_query_local(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response); extern int semanage_bool_exists_local(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response); extern int semanage_bool_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_bool_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg); extern int semanage_bool_list_local(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count); #endif libsemanage/include/semanage/booleans_policy.h0100644 0000000 0000000 00000001464 13756670064 020634 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_BOOLEANS_POLICY_H_ #define _SEMANAGE_BOOLEANS_POLICY_H_ #include #include extern int semanage_bool_query(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response); extern int semanage_bool_exists(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response); extern int semanage_bool_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_bool_iterate(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg); extern int semanage_bool_list(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count); #endif libsemanage/include/semanage/context_record.h0100644 0000000 0000000 00000003407 13756670064 020474 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_CONTEXT_RECORD_H_ #define _SEMANAGE_CONTEXT_RECORD_H_ #include #ifndef _SEMANAGE_CONTEXT_DEFINED_ struct semanage_context; typedef struct semanage_context semanage_context_t; #define _SEMANAGE_CONTEXT_DEFINED_ #endif /* User */ extern const char *semanage_context_get_user(const semanage_context_t * con); extern int semanage_context_set_user(semanage_handle_t * handle, semanage_context_t * con, const char *user); /* Role */ extern const char *semanage_context_get_role(const semanage_context_t * con); extern int semanage_context_set_role(semanage_handle_t * handle, semanage_context_t * con, const char *role); /* Type */ extern const char *semanage_context_get_type(const semanage_context_t * con); extern int semanage_context_set_type(semanage_handle_t * handle, semanage_context_t * con, const char *type); /* MLS */ extern const char *semanage_context_get_mls(const semanage_context_t * con); extern int semanage_context_set_mls(semanage_handle_t * handle, semanage_context_t * con, const char *mls_range); /* Create/Clone/Destroy */ extern int semanage_context_create(semanage_handle_t * handle, semanage_context_t ** con_ptr); extern int semanage_context_clone(semanage_handle_t * handle, const semanage_context_t * con, semanage_context_t ** con_ptr); extern void semanage_context_free(semanage_context_t * con); /* Parse to/from string */ extern int semanage_context_from_string(semanage_handle_t * handle, const char *str, semanage_context_t ** con); extern int semanage_context_to_string(semanage_handle_t * handle, const semanage_context_t * con, char **str_ptr); #endif libsemanage/include/semanage/debug.h0100644 0000000 0000000 00000003535 13756670064 016542 0ustar000000000 0000000 /* Author: Joshua Brindle * Jason Tang * Ivan Gyurdiev * * Copyright (C) 2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_DEBUG_H_ #define _SEMANAGE_DEBUG_H_ #include #define SEMANAGE_MSG_ERR 1 #define SEMANAGE_MSG_WARN 2 #define SEMANAGE_MSG_INFO 3 extern int semanage_msg_get_level(semanage_handle_t * handle); extern const char *semanage_msg_get_channel(semanage_handle_t * handle); extern const char *semanage_msg_get_fname(semanage_handle_t * handle); /* Set the messaging callback. * By the default, the callback will print * the message on standard output, in a * particular format. Passing NULL here * indicates that messaging should be suppressed */ extern void semanage_msg_set_callback(semanage_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, semanage_handle_t * handle, const char *fmt, ...), void *msg_callback_arg); #endif libsemanage/include/semanage/fcontext_record.h0100644 0000000 0000000 00000004643 13756670064 020645 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_FCONTEXT_RECORD_H_ #define _SEMANAGE_FCONTEXT_RECORD_H_ #include #include #ifndef _SEMANAGE_FCONTEXT_DEFINED_ struct semanage_fcontext; struct semanage_fcontext_key; typedef struct semanage_fcontext semanage_fcontext_t; typedef struct semanage_fcontext_key semanage_fcontext_key_t; #define _SEMANAGE_FCONTEXT_DEFINED_ #endif /* Key */ extern int semanage_fcontext_compare(const semanage_fcontext_t * fcontext, const semanage_fcontext_key_t * key); extern int semanage_fcontext_compare2(const semanage_fcontext_t * fcontext, const semanage_fcontext_t * fcontext2); extern int semanage_fcontext_key_create(semanage_handle_t * handle, const char *expr, int type, semanage_fcontext_key_t ** key_ptr); extern int semanage_fcontext_key_extract(semanage_handle_t * handle, const semanage_fcontext_t * fcontext, semanage_fcontext_key_t ** key_ptr); extern void semanage_fcontext_key_free(semanage_fcontext_key_t * key); /* Regexp */ extern const char *semanage_fcontext_get_expr(const semanage_fcontext_t * fcontext); extern int semanage_fcontext_set_expr(semanage_handle_t * handle, semanage_fcontext_t * fcontext, const char *expr); /* Type */ #define SEMANAGE_FCONTEXT_ALL 0 #define SEMANAGE_FCONTEXT_REG 1 #define SEMANAGE_FCONTEXT_DIR 2 #define SEMANAGE_FCONTEXT_CHAR 3 #define SEMANAGE_FCONTEXT_BLOCK 4 #define SEMANAGE_FCONTEXT_SOCK 5 #define SEMANAGE_FCONTEXT_LINK 6 #define SEMANAGE_FCONTEXT_PIPE 7 extern int semanage_fcontext_get_type(const semanage_fcontext_t * fcontext); extern const char *semanage_fcontext_get_type_str(int type); extern void semanage_fcontext_set_type(semanage_fcontext_t * fcontext, int type); /* Context */ extern semanage_context_t *semanage_fcontext_get_con(const semanage_fcontext_t * fcontext); extern int semanage_fcontext_set_con(semanage_handle_t * handle, semanage_fcontext_t * fcontext, semanage_context_t * con); /* Create/Clone/Destroy */ extern int semanage_fcontext_create(semanage_handle_t * handle, semanage_fcontext_t ** fcontext_ptr); extern int semanage_fcontext_clone(semanage_handle_t * handle, const semanage_fcontext_t * fcontext, semanage_fcontext_t ** fcontext_ptr); extern void semanage_fcontext_free(semanage_fcontext_t * fcontext); #endif libsemanage/include/semanage/fcontexts_local.h0100644 0000000 0000000 00000002237 13756670064 020641 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_FCONTEXTS_LOCAL_H_ #define _SEMANAGE_FCONTEXTS_LOCAL_H_ #include #include extern int semanage_fcontext_modify_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, const semanage_fcontext_t * data); extern int semanage_fcontext_del_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key); extern int semanage_fcontext_query_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, semanage_fcontext_t ** response); extern int semanage_fcontext_exists_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, int *response); extern int semanage_fcontext_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_fcontext_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_fcontext_t * record, void *varg), void *handler_arg); extern int semanage_fcontext_list_local(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count); #endif libsemanage/include/semanage/fcontexts_policy.h0100644 0000000 0000000 00000001774 13756670064 021053 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_FCONTEXTS_POLICY_H_ #define _SEMANAGE_FCONTEXTS_POLICY_H_ #include #include extern int semanage_fcontext_query(semanage_handle_t * handle, const semanage_fcontext_key_t * key, semanage_fcontext_t ** response); extern int semanage_fcontext_exists(semanage_handle_t * handle, const semanage_fcontext_key_t * key, int *response); extern int semanage_fcontext_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_fcontext_iterate(semanage_handle_t * handle, int (*handler) (const semanage_fcontext_t * record, void *varg), void *handler_arg); extern int semanage_fcontext_list(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count); extern int semanage_fcontext_list_homedirs(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count); #endif libsemanage/include/semanage/handle.h0100644 0000000 0000000 00000015632 13756670064 016710 0ustar000000000 0000000 /* Authors: Joshua Brindle * Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_HANDLE_H_ #define _SEMANAGE_HANDLE_H_ #include /* All accesses with semanage are through a "semanage_handle". The * handle may ultimately reference local config files, * the binary policy file, a module store, or a policy management server. */ struct semanage_handle; typedef struct semanage_handle semanage_handle_t; /* Create and return a semanage handle. The handle is initially in the disconnected state. */ semanage_handle_t *semanage_handle_create(void); /* Deallocate all space associated with a semanage_handle_t, including * the pointer itself. CAUTION: this function does not disconnect * from the backend; be sure that a semanage_disconnect() was * previously called if the handle was connected. */ void semanage_handle_destroy(semanage_handle_t *); /* This is the type of connection to the store, for now only * direct is supported */ enum semanage_connect_type { SEMANAGE_CON_INVALID = 0, SEMANAGE_CON_DIRECT, SEMANAGE_CON_POLSERV_LOCAL, SEMANAGE_CON_POLSERV_REMOTE }; /* This function allows you to specify the store to connect to. * It must be called after semanage_handle_create but before * semanage_connect. The argument should be the full path to the store. */ void semanage_select_store(semanage_handle_t * handle, char *path, enum semanage_connect_type storetype); /* Just reload the policy */ int semanage_reload_policy(semanage_handle_t * handle); /* set whether to reload the policy or not after a commit, * 1 for yes (default), 0 for no */ void semanage_set_reload(semanage_handle_t * handle, int do_reload); /* set whether to rebuild the policy on commit, even if no * changes were performed. * 1 for yes, 0 for no (default) */ void semanage_set_rebuild(semanage_handle_t * handle, int do_rebuild); /* Fills *compiler_path with the location of the hll compiler sh->conf->compiler_directory_path * corresponding to lang_ext. * Upon success returns 0, -1 on error. */ int semanage_get_hll_compiler_path(semanage_handle_t *sh, char *lang_ext, char **compiler_path); /* create the store if it does not exist, this only has an effect on * direct connections and must be called before semanage_connect * 1 for yes, 0 for no (default) */ void semanage_set_create_store(semanage_handle_t * handle, int create_store); /*Get whether or not dontaudits will be disabled upon commit */ int semanage_get_disable_dontaudit(semanage_handle_t * handle); /* Set whether or not to disable dontaudits upon commit */ void semanage_set_disable_dontaudit(semanage_handle_t * handle, int disable_dontaudit); /* Set whether or not to execute setfiles to check file contexts upon commit */ void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts); /* Get the default priority. */ uint16_t semanage_get_default_priority(semanage_handle_t *sh); /* Set the default priority. */ int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority); /* Check whether policy is managed via libsemanage on this system. * Must be called prior to trying to connect. * Return 1 if policy is managed via libsemanage on this system, * 0 if policy is not managed, or -1 on error. */ int semanage_is_managed(semanage_handle_t *); /* "Connect" to a manager based on the configuration and * associate the provided handle with the connection. * If the connect fails then this function returns a negative value, * else it returns zero. */ int semanage_connect(semanage_handle_t *); /* Disconnect from the manager given by the handle. If already * disconnected then this function does nothing. Return 0 if * disconnected properly or already disconnected, negative value on * error. */ int semanage_disconnect(semanage_handle_t *); /* Attempt to obtain a transaction lock on the manager. If another * process has the lock then this function may block, depending upon * the timeout value in the handle. * * Note that if the semanage_handle has not yet obtained a transaction * lock whenever a writer function is called, there will be an * implicit call to this function. */ int semanage_begin_transaction(semanage_handle_t *); /* Attempt to commit all changes since this transaction began. If the * commit is successful then increment the "policy sequence number" * and then release the transaction lock. Return that policy number * afterwards, or -1 on error. */ int semanage_commit(semanage_handle_t *); #define SEMANAGE_CAN_READ 1 #define SEMANAGE_CAN_WRITE 2 /* returns SEMANAGE_CAN_READ or SEMANAGE_CAN_WRITE if the store is readable * or writable, respectively. <0 if an error occurred */ int semanage_access_check(semanage_handle_t * sh); /* returns 0 if not connected, 1 if connected */ int semanage_is_connected(semanage_handle_t * sh); /* returns 1 if policy is MLS, 0 otherwise. */ int semanage_mls_enabled(semanage_handle_t *sh); /* Change to alternate semanage root path */ int semanage_set_root(const char *path); /* Get the current semanage root path */ const char * semanage_root(void); /* Get whether or not needless unused branch of tunables would be preserved */ int semanage_get_preserve_tunables(semanage_handle_t * handle); /* Set whether or not to preserve the needless unused branch of tunables */ void semanage_set_preserve_tunables(semanage_handle_t * handle, int preserve_tunables); /* Get the flag value for whether or not caching is ignored for compiled CIL modules from HLL files */ int semanage_get_ignore_module_cache(semanage_handle_t *handle); /* Set semanage_handle flag for whether or not to ignore caching of compiled CIL modules from HLL files */ void semanage_set_ignore_module_cache(semanage_handle_t *handle, int ignore_module_cache); /* set the store root path for semanage output files */ void semanage_set_store_root(semanage_handle_t *sh, const char *store_root); /* META NOTES * * For all functions a non-negative number indicates success. For some * functions a >=0 returned value is the "policy sequence number". This * number keeps tracks of policy revisions and is used to detect if * one semanage client has committed policy changes while another is * still connected. */ #endif libsemanage/include/semanage/ibendport_record.h0100644 0000000 0000000 00000004174 13756670064 021000 0ustar000000000 0000000 /*Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_IBENDPORT_RECORD_H_ #define _SEMANAGE_IBENDPORT_RECORD_H_ #include #include #include #ifndef _SEMANAGE_IBENDPORT_DEFINED_ struct semanage_ibendport; struct semanage_ibendport_key; typedef struct semanage_ibendport semanage_ibendport_t; typedef struct semanage_ibendport_key semanage_ibendport_key_t; #define _SEMANAGE_IBENDPORT_DEFINED_ #endif extern int semanage_ibendport_compare(const semanage_ibendport_t *ibendport, const semanage_ibendport_key_t *key); extern int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport, const semanage_ibendport_t *ibendport2); extern int semanage_ibendport_key_create(semanage_handle_t *handle, const char *ibdev_name, int port, semanage_ibendport_key_t **key_ptr); extern int semanage_ibendport_key_extract(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, semanage_ibendport_key_t **key_ptr); extern void semanage_ibendport_key_free(semanage_ibendport_key_t *key); extern int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, char **ibdev_name_ptr); extern int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle, semanage_ibendport_t *ibendport, const char *ibdev_name); extern int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport); extern void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port); extern semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport); extern int semanage_ibendport_set_con(semanage_handle_t *handle, semanage_ibendport_t *ibendport, semanage_context_t *con); extern int semanage_ibendport_create(semanage_handle_t *handle, semanage_ibendport_t **ibendport_ptr); extern int semanage_ibendport_clone(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, semanage_ibendport_t **ibendport_ptr); extern void semanage_ibendport_free(semanage_ibendport_t *ibendport); #endif libsemanage/include/semanage/ibendports_local.h0100644 0000000 0000000 00000002250 13756670064 020770 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc */ #ifndef _SEMANAGE_IBENDPORTS_LOCAL_H_ #define _SEMANAGE_IBENDPORTS_LOCAL_H_ #include #include extern int semanage_ibendport_modify_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, const semanage_ibendport_t *data); extern int semanage_ibendport_del_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key); extern int semanage_ibendport_query_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, semanage_ibendport_t **response); extern int semanage_ibendport_exists_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, int *response); extern int semanage_ibendport_count_local(semanage_handle_t *handle, unsigned int *response); extern int semanage_ibendport_iterate_local(semanage_handle_t *handle, int (*handler)(const semanage_ibendport_t *record, void *varg), void *handler_arg); extern int semanage_ibendport_list_local(semanage_handle_t *handle, semanage_ibendport_t ***records, unsigned int *count); #endif libsemanage/include/semanage/ibendports_policy.h0100644 0000000 0000000 00000001600 13756670064 021173 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Techonologies Inc */ #ifndef _SEMANAGE_IBENDPORTS_POLICY_H_ #define _SEMANAGE_IBENDPORTS_POLICY_H_ #include #include extern int semanage_ibendport_query(semanage_handle_t *handle, const semanage_ibendport_key_t *key, semanage_ibendport_t **response); extern int semanage_ibendport_exists(semanage_handle_t *handle, const semanage_ibendport_key_t *key, int *response); extern int semanage_ibendport_count(semanage_handle_t *handle, unsigned int *response); extern int semanage_ibendport_iterate(semanage_handle_t *handle, int (*handler)(const semanage_ibendport_t *record, void *varg), void *handler_arg); extern int semanage_ibendport_list(semanage_handle_t *handle, semanage_ibendport_t ***records, unsigned int *count); #endif libsemanage/include/semanage/ibpkey_record.h0100644 0000000 0000000 00000004572 13756670064 020277 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc */ #ifndef _SEMANAGE_IBPKEY_RECORD_H_ #define _SEMANAGE_IBPKEY_RECORD_H_ #include #include #include #include #ifndef _SEMANAGE_IBPKEY_DEFINED_ struct semanage_ibpkey; struct semanage_ibpkey_key; typedef struct semanage_ibpkey semanage_ibpkey_t; typedef struct semanage_ibpkey_key semanage_ibpkey_key_t; #define _SEMANAGE_IBPKEY_DEFINED_ #endif extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey, const semanage_ibpkey_key_t *key); extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey, const semanage_ibpkey_t *ibpkey2); extern int semanage_ibpkey_key_create(semanage_handle_t *handle, const char *subnet_prefix, int low, int high, semanage_ibpkey_key_t **key_ptr); extern int semanage_ibpkey_key_extract(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, semanage_ibpkey_key_t **key_ptr); extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key); extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, char **subnet_prefix_ptr); extern uint64_t semanage_ibpkey_get_subnet_prefix_bytes(const semanage_ibpkey_t *ibpkey); extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle, semanage_ibpkey_t *ibpkey, const char *subnet_prefix); extern void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey, uint64_t subnet_prefix); extern int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey); extern int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey); extern void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int pkey_num); extern void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low, int high); extern semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t *ibpkey); extern int semanage_ibpkey_set_con(semanage_handle_t *handle, semanage_ibpkey_t *ibpkey, semanage_context_t *con); extern int semanage_ibpkey_create(semanage_handle_t *handle, semanage_ibpkey_t **ibpkey_ptr); extern int semanage_ibpkey_clone(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, semanage_ibpkey_t **ibpkey_ptr); extern void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey); #endif libsemanage/include/semanage/ibpkeys_local.h0100644 0000000 0000000 00000002166 13756670064 020273 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc */ #ifndef _SEMANAGE_IBPKEYS_LOCAL_H_ #define _SEMANAGE_IBPKEYS_LOCAL_H_ #include #include extern int semanage_ibpkey_modify_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, const semanage_ibpkey_t *data); extern int semanage_ibpkey_del_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key); extern int semanage_ibpkey_query_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, semanage_ibpkey_t **response); extern int semanage_ibpkey_exists_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, int *response); extern int semanage_ibpkey_count_local(semanage_handle_t *handle, unsigned int *response); extern int semanage_ibpkey_iterate_local(semanage_handle_t *handle, int (*handler)(const semanage_ibpkey_t * record, void *varg), void *handler_arg); extern int semanage_ibpkey_list_local(semanage_handle_t *handle, semanage_ibpkey_t ***records, unsigned int *count); #endif libsemanage/include/semanage/ibpkeys_policy.h0100644 0000000 0000000 00000001475 13756670064 020502 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technolgies Inc. */ #ifndef _SEMANAGE_IBPKEYS_POLICY_H_ #define _SEMANAGE_IBPKEYS_POLICY_H_ #include #include extern int semanage_ibpkey_query(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, semanage_ibpkey_t **response); extern int semanage_ibpkey_exists(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, int *response); extern int semanage_ibpkey_count(semanage_handle_t *handle, unsigned int *response); extern int semanage_ibpkey_iterate(semanage_handle_t *handle, int (*handler)(const semanage_ibpkey_t *record, void *varg), void *handler_arg); extern int semanage_ibpkey_list(semanage_handle_t *handle, semanage_ibpkey_t ***records, unsigned int *count); #endif libsemanage/include/semanage/iface_record.h0100644 0000000 0000000 00000003713 13756670064 020057 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_IFACE_RECORD_H_ #define _SEMANAGE_IFACE_RECORD_H_ #include #include #ifndef _SEMANAGE_IFACE_DEFINED_ struct semanage_iface; struct semanage_iface_key; typedef struct semanage_iface semanage_iface_t; typedef struct semanage_iface_key semanage_iface_key_t; #define _SEMANAGE_IFACE_DEFINED_ #endif /* Key */ extern int semanage_iface_compare(const semanage_iface_t * iface, const semanage_iface_key_t * key); extern int semanage_iface_compare2(const semanage_iface_t * iface, const semanage_iface_t * iface2); extern int semanage_iface_key_create(semanage_handle_t * handle, const char *name, semanage_iface_key_t ** key_ptr); extern int semanage_iface_key_extract(semanage_handle_t * handle, const semanage_iface_t * iface, semanage_iface_key_t ** key_ptr); extern void semanage_iface_key_free(semanage_iface_key_t * key); /* Name */ extern const char *semanage_iface_get_name(const semanage_iface_t * iface); extern int semanage_iface_set_name(semanage_handle_t * handle, semanage_iface_t * iface, const char *name); /* Context */ extern semanage_context_t *semanage_iface_get_ifcon(const semanage_iface_t * iface); extern int semanage_iface_set_ifcon(semanage_handle_t * handle, semanage_iface_t * iface, semanage_context_t * con); extern semanage_context_t *semanage_iface_get_msgcon(const semanage_iface_t * iface); extern int semanage_iface_set_msgcon(semanage_handle_t * handle, semanage_iface_t * iface, semanage_context_t * con); /* Create/Clone/Destroy */ extern int semanage_iface_create(semanage_handle_t * handle, semanage_iface_t ** iface_ptr); extern int semanage_iface_clone(semanage_handle_t * handle, const semanage_iface_t * iface, semanage_iface_t ** iface_ptr); extern void semanage_iface_free(semanage_iface_t * iface); #endif libsemanage/include/semanage/interfaces_local.h0100644 0000000 0000000 00000002177 13756670064 020752 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_INTERFACES_LOCAL_H_ #define _SEMANAGE_INTERFACES_LOCAL_H_ #include #include extern int semanage_iface_modify_local(semanage_handle_t * handle, const semanage_iface_key_t * key, const semanage_iface_t * data); extern int semanage_iface_del_local(semanage_handle_t * handle, const semanage_iface_key_t * key); extern int semanage_iface_query_local(semanage_handle_t * handle, const semanage_iface_key_t * key, semanage_iface_t ** response); extern int semanage_iface_exists_local(semanage_handle_t * handle, const semanage_iface_key_t * key, int *response); extern int semanage_iface_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_iface_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_iface_t * record, void *varg), void *handler_arg); extern int semanage_iface_list_local(semanage_handle_t * handle, semanage_iface_t *** records, unsigned int *count); #endif libsemanage/include/semanage/interfaces_policy.h0100644 0000000 0000000 00000001502 13756670064 021146 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_INTERFACES_POLICY_H_ #define _SEMANAGE_INTERFACES_POLICY_H_ #include #include extern int semanage_iface_query(semanage_handle_t * handle, const semanage_iface_key_t * key, semanage_iface_t ** response); extern int semanage_iface_exists(semanage_handle_t * handle, const semanage_iface_key_t * key, int *response); extern int semanage_iface_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_iface_iterate(semanage_handle_t * handle, int (*handler) (const semanage_iface_t * record, void *varg), void *handler_arg); extern int semanage_iface_list(semanage_handle_t * handle, semanage_iface_t *** records, unsigned int *count); #endif libsemanage/include/semanage/modules.h0100644 0000000 0000000 00000020761 13756670064 017124 0ustar000000000 0000000 /* Authors: Joshua Brindle * Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_MODULES_H_ #define _SEMANAGE_MODULES_H_ #include #include #include #include typedef struct semanage_module_key semanage_module_key_t; /* High level module management functions. These are all part of * a transaction */ int semanage_module_install(semanage_handle_t *, char *module_data, size_t data_len, char *name, char *ext_lang); int semanage_module_install_file(semanage_handle_t *, const char *module_name); int semanage_module_remove(semanage_handle_t *, char *module_name); /* semanage_module_info is for getting information on installed modules, only name at this time */ typedef struct semanage_module_info semanage_module_info_t; /* Look up a module using @modkey. The module's raw data is returned as a * @mapped_data blob and size of the mapped_data is returned as @data_len. * @modinfo contains additional information which can be used by the caller such * as the high level language extension of @mapped_data. * * On success, the caller is responsible for unmapping @mapped_data with munmap(), * destroying @modinfo with semanage_module_info_destroy(), and freeing @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_extract(semanage_handle_t *sh, semanage_module_key_t *modkey, int extract_cil, void **mapped_data, size_t *data_len, semanage_module_info_t **modinfo); int semanage_module_list(semanage_handle_t *, semanage_module_info_t **, int *num_modules); void semanage_module_info_datum_destroy(semanage_module_info_t *); semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list, int n); const char *semanage_module_get_name(semanage_module_info_t *); /* Module Info */ /* Creates a module info struct. * * Returns 0 on success and -1 on failure. * * The @modinfo should be destroyed with semanage_module_info_destroy. * The caller should call free() on the struct. */ int semanage_module_info_create(semanage_handle_t *sh, semanage_module_info_t **modinfo); /* Frees the members of the module info struct. * * Returns 0 on success and -1 on failure. * * The caller should call free() on the struct. */ int semanage_module_info_destroy(semanage_handle_t *handle, semanage_module_info_t *modinfo); /* Module Info Getters */ /* Get @priority from @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_get_priority(semanage_handle_t *sh, semanage_module_info_t *modinfo, uint16_t *priority); /* Get @name from @modinfo. Caller should not free @name. * * Returns 0 on success and -1 on error. */ int semanage_module_info_get_name(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char **name); /* Get @lang_ext from @modinfo. Caller should not free @lang_ext. * * Returns 0 on success and -1 on error. */ int semanage_module_info_get_lang_ext(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char **lang_ext); /* Get @enabled from @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_get_enabled(semanage_handle_t *sh, semanage_module_info_t *modinfo, int *enabled); /* Module Info Setters */ /* Set @priority in @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_set_priority(semanage_handle_t *sh, semanage_module_info_t *modinfo, uint16_t priority); /* Set @name in @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_set_name(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char *name); /* Set @lang_ext in @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_set_lang_ext(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char *lang_ext); /* Set @enabled in @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_info_set_enabled(semanage_handle_t *sh, semanage_module_info_t *modinfo, int enabled); /* Module Key */ /* Creates a module key struct. * * Return 0 on success, and -1 on error. * * The @modkey should be destroyed with semanage_module_key_destroy. * The caller should call free() on the struct. */ int semanage_module_key_create(semanage_handle_t *sh, semanage_module_key_t **modkey); /* Frees members of the @modkey, but not the struct. The caller should * call free() on struct. * * Returns 0 on success, and -1 on error. */ int semanage_module_key_destroy(semanage_handle_t *sh, semanage_module_key_t *modkey); /* Module Key Getters */ /* Get @name from @modkey. Caller should not free @name. * * Returns 0 on success and -1 on error. */ int semanage_module_key_get_name(semanage_handle_t *sh, semanage_module_key_t *modkey, const char **name); /* Get @name from @modkey. * * Returns 0 on success and -1 on error. */ int semanage_module_key_get_priority(semanage_handle_t *sh, semanage_module_key_t *modkey, uint16_t *priority); /* Module Key Setters */ /* Set @name in @modkey. * * Returns 0 on success and -1 on error. */ int semanage_module_key_set_name(semanage_handle_t *sh, semanage_module_key_t *modkey, const char *name); /* Set @priority in @modkey. * * Returns 0 on success and -1 on error. */ int semanage_module_key_set_priority(semanage_handle_t *sh, semanage_module_key_t *modkey, uint16_t priority); /* Set module @enabled status from @modkey. Modules are enabled on a per * module name basis (across all priorities). @modkey only needs to have * name set (priority is ignored). * * Returns 0 on success and -1 on error. */ int semanage_module_set_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int enabled); /* Lookup @modinfo by @modkey. Caller should use * semanage_module_info_destroy and free on @modinfo. * * Returns 0 on success and -1 on error. */ int semanage_module_get_module_info(semanage_handle_t *sh, const semanage_module_key_t *modkey, semanage_module_info_t **modinfo); /* Create a list of all modules in @modinfos of length @modinfos_len. * The list will be sorted from high priority to low and alphabetically * by module name within a priority. * * Caller should use semanage_module_info_destroy on each modinfo in * @modinfos and free on @modinfos. * * Returns 0 on success and -1 on error. */ int semanage_module_list_all(semanage_handle_t *sh, semanage_module_info_t **modinfos, int *modinfos_len); /* Install the module indicated by @modinfo with input data from * @module_data with length @data_len. * * @modinfo must have all values filled in. * @module_data may be bzip compressed. * * Returns: * 0 success * -1 failure, out of memory * -2 failure, invalid @modinfo * -3 failure, error writing file */ int semanage_module_install_info(semanage_handle_t *sh, const semanage_module_info_t *modinfo, char *data, size_t data_len); /* Remove the module indicated by @modkey. * @modkey must have key values filled in. * * Returns: * 0 success * -1 failure, out of memeory * -2 failure, @module not found or couldn't be removed */ int semanage_module_remove_key(semanage_handle_t *sh, const semanage_module_key_t *modkey); /* Module Enabled */ /* Get module @enabled status from @modkey. Modules are enabled on a per * module name basis (across all priorities). @modkey only needs to have * name set (priority is ignored). * * Returns 0 on success and -1 on error. */ int semanage_module_get_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int *enabled); #endif libsemanage/include/semanage/node_record.h0100644 0000000 0000000 00000005522 13756670064 017735 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_NODE_RECORD_H_ #define _SEMANAGE_NODE_RECORD_H_ #include #include #include #ifndef _SEMANAGE_NODE_DEFINED_ struct semanage_node; struct semanage_node_key; typedef struct semanage_node semanage_node_t; typedef struct semanage_node_key semanage_node_key_t; #define _SEMANAGE_NODE_DEFINED_ #endif #define SEMANAGE_PROTO_IP4 0 #define SEMANAGE_PROTO_IP6 1 /* Key */ extern int semanage_node_compare(const semanage_node_t * node, const semanage_node_key_t * key); extern int semanage_node_compare2(const semanage_node_t * node, const semanage_node_t * node2); extern int semanage_node_key_create(semanage_handle_t * handle, const char *addr, const char *mask, int proto, semanage_node_key_t ** key_ptr); extern int semanage_node_key_extract(semanage_handle_t * handle, const semanage_node_t * node, semanage_node_key_t ** key_ptr); extern void semanage_node_key_free(semanage_node_key_t * key); /* Address */ extern int semanage_node_get_addr(semanage_handle_t * handle, const semanage_node_t * node, char **addr); extern int semanage_node_get_addr_bytes(semanage_handle_t * handle, const semanage_node_t * node, char **addr, size_t * addr_sz); extern int semanage_node_set_addr(semanage_handle_t * handle, semanage_node_t * node, int proto, const char *addr); extern int semanage_node_set_addr_bytes(semanage_handle_t * handle, semanage_node_t * node, const char *addr, size_t addr_sz); /* Netmask */ extern int semanage_node_get_mask(semanage_handle_t * handle, const semanage_node_t * node, char **mask); extern int semanage_node_get_mask_bytes(semanage_handle_t * handle, const semanage_node_t * node, char **mask, size_t * mask_sz); extern int semanage_node_set_mask(semanage_handle_t * handle, semanage_node_t * node, int proto, const char *mask); extern int semanage_node_set_mask_bytes(semanage_handle_t * handle, semanage_node_t * node, const char *mask, size_t mask_sz); /* Protocol */ extern int semanage_node_get_proto(const semanage_node_t * node); extern void semanage_node_set_proto(semanage_node_t * node, int proto); extern const char *semanage_node_get_proto_str(int proto); /* Context */ extern semanage_context_t *semanage_node_get_con(const semanage_node_t * node); extern int semanage_node_set_con(semanage_handle_t * handle, semanage_node_t * node, semanage_context_t * con); /* Create/Clone/Destroy */ extern int semanage_node_create(semanage_handle_t * handle, semanage_node_t ** node_ptr); extern int semanage_node_clone(semanage_handle_t * handle, const semanage_node_t * node, semanage_node_t ** node_ptr); extern void semanage_node_free(semanage_node_t * node); #endif libsemanage/include/semanage/nodes_local.h0100644 0000000 0000000 00000002155 13756670064 017733 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_NODES_LOCAL_H_ #define _SEMANAGE_NODES_LOCAL_H_ #include #include extern int semanage_node_modify_local(semanage_handle_t * handle, const semanage_node_key_t * key, const semanage_node_t * data); extern int semanage_node_del_local(semanage_handle_t * handle, const semanage_node_key_t * key); extern int semanage_node_query_local(semanage_handle_t * handle, const semanage_node_key_t * key, semanage_node_t ** response); extern int semanage_node_exists_local(semanage_handle_t * handle, const semanage_node_key_t * key, int *response); extern int semanage_node_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_node_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_node_t * record, void *varg), void *handler_arg); extern int semanage_node_list_local(semanage_handle_t * handle, semanage_node_t *** records, unsigned int *count); #endif libsemanage/include/semanage/nodes_policy.h0100644 0000000 0000000 00000001453 13756670064 020140 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_NODES_POLICY_H_ #define _SEMANAGE_NODES_POLICY_H_ #include #include extern int semanage_node_query(semanage_handle_t * handle, const semanage_node_key_t * key, semanage_node_t ** response); extern int semanage_node_exists(semanage_handle_t * handle, const semanage_node_key_t * key, int *response); extern int semanage_node_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_node_iterate(semanage_handle_t * handle, int (*handler) (const semanage_node_t * record, void *varg), void *handler_arg); extern int semanage_node_list(semanage_handle_t * handle, semanage_node_t *** records, unsigned int *count); #endif libsemanage/include/semanage/port_record.h0100644 0000000 0000000 00000004041 13756670064 017767 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_PORT_RECORD_H_ #define _SEMANAGE_PORT_RECORD_H_ #include #include #ifndef _SEMANAGE_PORT_DEFINED_ struct semanage_port; struct semanage_port_key; typedef struct semanage_port semanage_port_t; typedef struct semanage_port_key semanage_port_key_t; #define _SEMANAGE_PORT_DEFINED_ #endif #define SEMANAGE_PROTO_UDP 0 #define SEMANAGE_PROTO_TCP 1 /* Key */ extern int semanage_port_compare(const semanage_port_t * port, const semanage_port_key_t * key); extern int semanage_port_compare2(const semanage_port_t * port, const semanage_port_t * port2); extern int semanage_port_key_create(semanage_handle_t * handle, int low, int high, int proto, semanage_port_key_t ** key_ptr); extern int semanage_port_key_extract(semanage_handle_t * handle, const semanage_port_t * port, semanage_port_key_t ** key_ptr); extern void semanage_port_key_free(semanage_port_key_t * key); /* Protocol */ extern int semanage_port_get_proto(const semanage_port_t * port); extern void semanage_port_set_proto(semanage_port_t * port, int proto); extern const char *semanage_port_get_proto_str(int proto); /* Port */ extern int semanage_port_get_low(const semanage_port_t * port); extern int semanage_port_get_high(const semanage_port_t * port); extern void semanage_port_set_port(semanage_port_t * port, int port_num); extern void semanage_port_set_range(semanage_port_t * port, int low, int high); /* Context */ extern semanage_context_t *semanage_port_get_con(const semanage_port_t * port); extern int semanage_port_set_con(semanage_handle_t * handle, semanage_port_t * port, semanage_context_t * con); /* Create/Clone/Destroy */ extern int semanage_port_create(semanage_handle_t * handle, semanage_port_t ** port_ptr); extern int semanage_port_clone(semanage_handle_t * handle, const semanage_port_t * port, semanage_port_t ** port_ptr); extern void semanage_port_free(semanage_port_t * port); #endif libsemanage/include/semanage/ports_local.h0100644 0000000 0000000 00000002155 13756670064 017772 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_PORTS_LOCAL_H_ #define _SEMANAGE_PORTS_LOCAL_H_ #include #include extern int semanage_port_modify_local(semanage_handle_t * handle, const semanage_port_key_t * key, const semanage_port_t * data); extern int semanage_port_del_local(semanage_handle_t * handle, const semanage_port_key_t * key); extern int semanage_port_query_local(semanage_handle_t * handle, const semanage_port_key_t * key, semanage_port_t ** response); extern int semanage_port_exists_local(semanage_handle_t * handle, const semanage_port_key_t * key, int *response); extern int semanage_port_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_port_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_port_t * record, void *varg), void *handler_arg); extern int semanage_port_list_local(semanage_handle_t * handle, semanage_port_t *** records, unsigned int *count); #endif libsemanage/include/semanage/ports_policy.h0100644 0000000 0000000 00000001453 13756670064 020177 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_PORTS_POLICY_H_ #define _SEMANAGE_PORTS_POLICY_H_ #include #include extern int semanage_port_query(semanage_handle_t * handle, const semanage_port_key_t * key, semanage_port_t ** response); extern int semanage_port_exists(semanage_handle_t * handle, const semanage_port_key_t * key, int *response); extern int semanage_port_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_port_iterate(semanage_handle_t * handle, int (*handler) (const semanage_port_t * record, void *varg), void *handler_arg); extern int semanage_port_list(semanage_handle_t * handle, semanage_port_t *** records, unsigned int *count); #endif libsemanage/include/semanage/semanage.h0100644 0000000 0000000 00000004133 13756670064 017227 0ustar000000000 0000000 /* Authors: Joshua Brindle * Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_SEMANAGE_H_ #define _SEMANAGE_SEMANAGE_H_ #include #include #include /* Records */ #include #include #include #include #include #include #include #include #include /* Dbase */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif libsemanage/include/semanage/seuser_record.h0100644 0000000 0000000 00000003605 13756670064 020316 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_SEUSER_RECORD_H_ #define _SEMANAGE_SEUSER_RECORD_H_ #include struct semanage_seuser; struct semanage_seuser_key; typedef struct semanage_seuser semanage_seuser_t; typedef struct semanage_seuser_key semanage_seuser_key_t; /* Key */ extern int semanage_seuser_key_create(semanage_handle_t * handle, const char *name, semanage_seuser_key_t ** key); extern int semanage_seuser_key_extract(semanage_handle_t * handle, const semanage_seuser_t * seuser, semanage_seuser_key_t ** key); extern void semanage_seuser_key_free(semanage_seuser_key_t * key); extern int semanage_seuser_compare(const semanage_seuser_t * seuser, const semanage_seuser_key_t * key); extern int semanage_seuser_compare2(const semanage_seuser_t * seuser, const semanage_seuser_t * seuser2); /* Name */ extern const char *semanage_seuser_get_name(const semanage_seuser_t * seuser); extern int semanage_seuser_set_name(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *name); /* Selinux Name */ extern const char *semanage_seuser_get_sename(const semanage_seuser_t * seuser); extern int semanage_seuser_set_sename(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *sename); /* MLS */ extern const char *semanage_seuser_get_mlsrange(const semanage_seuser_t * seuser); extern int semanage_seuser_set_mlsrange(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *mls_range); /* Create/Clone/Destroy */ extern int semanage_seuser_create(semanage_handle_t * handle, semanage_seuser_t ** seuser_ptr); extern int semanage_seuser_clone(semanage_handle_t * handle, const semanage_seuser_t * seuser, semanage_seuser_t ** seuser_ptr); extern void semanage_seuser_free(semanage_seuser_t * seuser); #endif libsemanage/include/semanage/seusers_local.h0100644 0000000 0000000 00000002172 13756670064 020313 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_SEUSERS_LOCAL_H_ #define _SEMANAGE_SEUSERS_LOCAL_H_ #include #include extern int semanage_seuser_modify_local(semanage_handle_t * handle, const semanage_seuser_key_t * key, const semanage_seuser_t * data); extern int semanage_seuser_del_local(semanage_handle_t * handle, const semanage_seuser_key_t * key); extern int semanage_seuser_query_local(semanage_handle_t * handle, const semanage_seuser_key_t * key, semanage_seuser_t ** response); extern int semanage_seuser_exists_local(semanage_handle_t * handle, const semanage_seuser_key_t * key, int *response); extern int semanage_seuser_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_seuser_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_seuser_t * record, void *varg), void *handler_arg); extern int semanage_seuser_list_local(semanage_handle_t * handle, semanage_seuser_t *** records, unsigned int *count); #endif libsemanage/include/semanage/seusers_policy.h0100644 0000000 0000000 00000001503 13756670064 020515 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_SEUSERS_POLICY_H_ #define _SEMANAGE_SEUSERS_POLICY_H_ #include #include extern int semanage_seuser_query(semanage_handle_t * handle, const semanage_seuser_key_t * key, semanage_seuser_t ** response); extern int semanage_seuser_exists(semanage_handle_t * handle, const semanage_seuser_key_t * key, int *response); extern int semanage_seuser_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_seuser_iterate(semanage_handle_t * handle, int (*handler) (const semanage_seuser_t * record, void *varg), void *handler_arg); extern int semanage_seuser_list(semanage_handle_t * handle, semanage_seuser_t *** records, unsigned int *count); #endif libsemanage/include/semanage/user_record.h0100644 0000000 0000000 00000005367 13756670064 017775 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_USER_RECORD_H_ #define _SEMANAGE_USER_RECORD_H_ #include #include struct semanage_user; typedef struct semanage_user semanage_user_t; #ifndef _SEMANAGE_USER_KEY_DEFINED_ struct semanage_user_key; typedef struct semanage_user_key semanage_user_key_t; #define _SEMANAGE_USER_KEY_DEFINED_ #endif /* Key */ extern int semanage_user_key_create(semanage_handle_t * handle, const char *name, semanage_user_key_t ** key); extern int semanage_user_key_extract(semanage_handle_t * handle, const semanage_user_t * user, semanage_user_key_t ** key); extern void semanage_user_key_free(semanage_user_key_t * key); extern int semanage_user_compare(const semanage_user_t * user, const semanage_user_key_t * key); extern int semanage_user_compare2(const semanage_user_t * user, const semanage_user_t * user2); /* Name */ extern const char *semanage_user_get_name(const semanage_user_t * user); extern int semanage_user_set_name(semanage_handle_t * handle, semanage_user_t * user, const char *name); /* Labeling prefix */ extern const char *semanage_user_get_prefix(const semanage_user_t * user); extern int semanage_user_set_prefix(semanage_handle_t * handle, semanage_user_t * user, const char *name); /* MLS */ extern const char *semanage_user_get_mlslevel(const semanage_user_t * user); extern int semanage_user_set_mlslevel(semanage_handle_t * handle, semanage_user_t * user, const char *mls_level); extern const char *semanage_user_get_mlsrange(const semanage_user_t * user); extern int semanage_user_set_mlsrange(semanage_handle_t * handle, semanage_user_t * user, const char *mls_range); /* Role management */ extern int semanage_user_get_num_roles(const semanage_user_t * user); extern int semanage_user_add_role(semanage_handle_t * handle, semanage_user_t * user, const char *role); extern void semanage_user_del_role(semanage_user_t * user, const char *role); extern int semanage_user_has_role(const semanage_user_t * user, const char *role); extern int semanage_user_get_roles(semanage_handle_t * handle, const semanage_user_t * user, const char ***roles_arr, unsigned int *num_roles); extern int semanage_user_set_roles(semanage_handle_t * handle, semanage_user_t * user, const char **roles_arr, unsigned int num_roles); /* Create/Clone/Destroy */ extern int semanage_user_create(semanage_handle_t * handle, semanage_user_t ** user_ptr); extern int semanage_user_clone(semanage_handle_t * handle, const semanage_user_t * user, semanage_user_t ** user_ptr); extern void semanage_user_free(semanage_user_t * user); #endif libsemanage/include/semanage/users_local.h0100644 0000000 0000000 00000002155 13756670064 017764 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_USERS_LOCAL_H_ #define _SEMANAGE_USERS_LOCAL_H_ #include #include extern int semanage_user_modify_local(semanage_handle_t * handle, const semanage_user_key_t * key, const semanage_user_t * data); extern int semanage_user_del_local(semanage_handle_t * handle, const semanage_user_key_t * key); extern int semanage_user_query_local(semanage_handle_t * handle, const semanage_user_key_t * key, semanage_user_t ** response); extern int semanage_user_exists_local(semanage_handle_t * handle, const semanage_user_key_t * key, int *response); extern int semanage_user_count_local(semanage_handle_t * handle, unsigned int *response); extern int semanage_user_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_user_t * record, void *varg), void *handler_arg); extern int semanage_user_list_local(semanage_handle_t * handle, semanage_user_t *** records, unsigned int *count); #endif libsemanage/include/semanage/users_policy.h0100644 0000000 0000000 00000001453 13756670064 020171 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_USERS_POLICY_H_ #define _SEMANAGE_USERS_POLICY_H_ #include #include extern int semanage_user_query(semanage_handle_t * handle, const semanage_user_key_t * key, semanage_user_t ** response); extern int semanage_user_exists(semanage_handle_t * handle, const semanage_user_key_t * key, int *response); extern int semanage_user_count(semanage_handle_t * handle, unsigned int *response); extern int semanage_user_iterate(semanage_handle_t * handle, int (*handler) (const semanage_user_t * record, void *varg), void *handler_arg); extern int semanage_user_list(semanage_handle_t * handle, semanage_user_t *** records, unsigned int *count); #endif libsemanage/man/0040755 0000000 0000000 00000000000 13756670064 012650 5ustar000000000 0000000 libsemanage/man/Makefile0100644 0000000 0000000 00000001413 13756670064 014304 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 MAN5SUBDIR ?= man5 MAN3DIR ?= $(MANDIR)/$(MAN3SUBDIR) MAN5DIR ?= $(MANDIR)/$(MAN5SUBDIR) all: install: all mkdir -p $(DESTDIR)$(MAN3DIR) mkdir -p $(DESTDIR)$(MAN5DIR) install -m 644 man3/*.3 $(DESTDIR)$(MAN3DIR) install -m 644 man5/*.5 $(DESTDIR)$(MAN5DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man3 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ install -m 644 $${lang}/man3/*.3 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ fi ; \ if [ -e $${lang}/man5 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN5SUBDIR) ; \ install -m 644 $${lang}/man5/*.5 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN5SUBDIR) ; \ fi ; \ done libsemanage/man/man3/0040755 0000000 0000000 00000000000 13756670064 013506 5ustar000000000 0000000 libsemanage/man/man3/semanage_bool.30100644 0000000 0000000 00000006453 13756670064 016372 0ustar000000000 0000000 .TH semanage_bool 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_bool \- SELinux Policy Booleans Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .br .B #include .PP This object contains properties associated with a SELinux policy boolean .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_bool_create "(3)" \- .br create a boolean .HP .BR semanage_bool_free "(3)" \- .br release resources for this boolean .HP .BR semanage_bool_key_create "(3)" \- .br create a key, which can be used to identify a boolean .HP .BR semanage_bool_key_free "(3)" \- .br release resources for this boolean key .HP .BR semanage_bool_key_extract "(3)" \- .br create a key matching this boolean .HP .BR semanage_bool_clone "(3)" \- .br create an identical boolean (deep-copy clone) .HP .BR semanage_bool_compare "(3)" \- .br compare this boolean to the provided key .HP .BR semanage_bool_compare2 "(3)" \- .br compare this boolean to another .SH "Properties API Overview" .HP .BR semanage_bool_get_name "(3)" \- .br return the name of this boolean .HP .BR semanage_bool_set_name "(3)" \- .br set the name of this boolean .HP .BR semanage_bool_get_value "(3)" \- .br return the value of this boolean .HP .BR semanage_bool_set_value "(3)" \- .br set the value of this boolean .SH "Record Store API Overview" .HP .BR semanage_bool_modify_local "(3)" \- .br add or update a boolean in the local store .HP .BR semanage_bool_set_active "(3)" \- .br update a boolean in the currently active policy .HP .BR semanage_bool_del_local "(3)" \- .br delete a boolean from the local store .HP .BR semanage_bool_exists "(3)" \- .br check if a boolean is defined in the persistent policy .HP .BR semanage_bool_exists_local "(3)" \- .br check if a boolean is defined in the local store .HP .BR semanage_bool_exists_active "(3)" \- .br check if a boolean is defined in the currently active policy .HP .BR semanage_bool_query "(3)" \- .br query a boolean in the persistent policy .HP .BR semanage_bool_query_local "(3)" \- .br query a boolean in the local store .HP .BR semanage_bool_query_active "(3)" \- .br query a boolean in the currently active policy .HP .BR semanage_bool_count "(3)" \- .br count the number of booleans defined in the persistent policy .HP .BR semanage_bool_count_local "(3)" \- .br count the number of booleans defined in the local store .HP .BR semanage_bool_count_active "(3)" \- .br count the number of booleans defined in the currently active policy .HP .BR semanage_bool_iterate "(3)" \- .br execute a callback for each boolean in the persistent policy .HP .BR semanage_bool_iterate_local "(3)" \- .br execute a callback for each boolean in the local store .HP .BR semanage_bool_iterate_active "(3)" \- .br execute a callback for each boolean in the currently active policy .HP .BR semanage_bool_list "(3)" \- .br return an array containing all booleans in the persistent policy .HP .BR semanage_bool_list_local "(3)" \- .br return an array containing all booleans in the local store .HP .BR semanage_bool_list_active "(3)" \- .br return an array containing all booleans in the currently active policy libsemanage/man/man3/semanage_bool_count.30100644 0000000 0000000 00000000032 13756670064 017565 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_bool_count_active.30100644 0000000 0000000 00000000032 13756670064 021120 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_bool_count_local.30100644 0000000 0000000 00000000032 13756670064 020737 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_bool_del_local.30100644 0000000 0000000 00000000030 13756670064 020351 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_bool_exists.30100644 0000000 0000000 00000000033 13756670064 017755 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_bool_exists_active.30100644 0000000 0000000 00000000033 13756670064 021310 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_bool_exists_local.30100644 0000000 0000000 00000000033 13756670064 021127 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_bool_iterate.30100644 0000000 0000000 00000000034 13756670064 020074 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_bool_iterate_active.30100644 0000000 0000000 00000000034 13756670064 021427 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_bool_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021246 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_bool_list.30100644 0000000 0000000 00000000031 13756670064 017407 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_bool_list_active.30100644 0000000 0000000 00000000031 13756670064 020742 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_bool_list_local.30100644 0000000 0000000 00000000031 13756670064 020561 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_bool_modify_local.30100644 0000000 0000000 00000000033 13756670064 021077 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_bool_query.30100644 0000000 0000000 00000000032 13756670064 017602 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_bool_query_active.30100644 0000000 0000000 00000000032 13756670064 021135 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_bool_query_local.30100644 0000000 0000000 00000000032 13756670064 020754 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_bool_set_active.30100644 0000000 0000000 00000003067 13756670064 020576 0ustar000000000 0000000 .TH semanage_bool_set_local 3 "4 January 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_bool_set_active \- update an existing SELinux boolean in the currently active policy .SH "SYNOPSIS" .B #include .br .sp .B extern int semanage_bool_set_active ( .br .BI " semanage_handle_t *" handle "," .br .BI " const semanage_bool_key_t *" key "," .br .BI " const semanage_bool_t *" data ");" .SH "DESCRIPTION" .TP .B Behavior: The set function will fail if no matching key is found in the local store. Otherwise, the provided object will replace the current one. When .BR semanage_commit "(3)" is invoked, changes will be written permanently into the local store, and will be loaded into policy. Validity of the object being added is checked at commit time. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I key identifies the .I data object, which will be written into the store. The key are data are properties of the caller, and are not stored or modified internally. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ), and must be executed in a transaction (see .BR semanage_begin_transaction "(3)" ). .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise 0 is returned. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_begin_transaction "(3), " semanage_connect "(3), " semanage_commit "(3). " libsemanage/man/man3/semanage_count.30100644 0000000 0000000 00000002243 13756670064 016560 0ustar000000000 0000000 .TH semanage_count 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_count \- SELinux Management API .SH "SYNOPSIS" The following count function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int COUNT_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " unsigned int* " response ");" .SH "DESCRIPTION" .TP .B Behavior: The count function will return the number of all objects in the selected location. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The number of objects will be stored at the location pointed by .I response. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ) .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_del.30100644 0000000 0000000 00000002771 13756670064 016202 0ustar000000000 0000000 .TH semanage_del 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_del \- SELinux Management API .SH "SYNOPSIS" The following delete function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int DELETE_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " const semanage_OBJECT_key_t *" key ");" .SH "DESCRIPTION" .TP .B Behavior: The delete function will remove the object corresponding to the provided key from the local store. If no match is found, no action is taken. Changes will become permanent when .BR semanage_commit "(3)" is invoked. Additional checks may be performed at that time to ensure the system is left in a valid state. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I key identifies the .I data object, which will be deleted from the local store. The key is a property of the caller, and will not be stored or modified internally. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ), and must be executed in a transaction (see .BR semanage_begin_transaction "(3)" ). .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise 0 is returned. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_begin_transaction "(3), " semanage_connect "(3), " semanage_commit "(3). " libsemanage/man/man3/semanage_exists.30100644 0000000 0000000 00000002556 13756670064 016756 0ustar000000000 0000000 .TH semanage_exists 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_exists \- SELinux Management API .SH "SYNOPSIS" The following exists function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int EXISTS_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " const semanage_OBJECT_key_t *" key "," .br .BI " semanage_OBJECT_t **" response ");" .SH "DESCRIPTION" .TP .B Behavior: The exists function will return 0 if a matching key is not found, and 1 otherwise. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I key identifies the object being checked. The result of the test will be stored in the address pointed by .I response The key is a property of the caller, and will not be stored or modified internally. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ) .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other read calls to the semanage database until the next commit. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_fcontext.30100644 0000000 0000000 00000006467 13756670064 017276 0ustar000000000 0000000 .TH semanage_fcontext 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_fcontext \- SELinux File Context Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a SELinux file context specification .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_fcontext_create "(3)" \- .br create a file context spec .HP .BR semanage_fcontext_free "(3)" \- .br release resources for this file context spec .HP .BR semanage_fcontext_key_create "(3)" \- .br create a key, which can be used to identify a file context spec .HP .BR semanage_fcontext_key_free "(3)" \- .br release resources for this file context spec key .HP .BR semanage_fcontext_key_extract "(3)" \- .br create a key matching this file context spec .HP .BR semanage_fcontext_clone "(3)" \- .br create an identical file context spec (deep-copy clone) .HP .BR semanage_fcontext_compare "(3)" \- .br compare this file context spec to the provided key .HP .BR semanage_fcontext_compare2 "(3)" \- .br compare this file context spec to another .SH "Properties API Overview" .HP .BR semanage_fcontext_get_expr "(3)" \- .br return the regular expression for this file context spec .HP .BR semanage_fcontext_set_expr "(3)" \- .br set the regular expression for this file context spec .HP .BR semanage_fcontext_get_type "(3)" \- .br return the file type for this file context spec .HP .BR semanage_fcontext_get_type_str "(3)" \- .br return a string representation for this file context spec type .HP .BR semanage_fcontext_set_type "(3)" \- .br set the file type for this file context spec .HP .BR semanage_fcontext_get_con "(3)" \- .br return the SELinux context for this file context spec .HP .BR semanage_fcontext_set_expr "(3)" \- .br set the SELinux context for this file context spec .SH "Record Store API Overview" .HP .BR semanage_fcontext_modify_local "(3)" \- .br add or update a file context spec in the local store .HP .BR semanage_fcontext_del_local "(3)" \- .br delete a file context spec from the local store .HP .BR semanage_fcontext_exists "(3)" \- .br check if a file context spec is defined in the persistent policy .HP .BR semanage_fcontext_exists_local "(3)" \- .br check if a file context spec is defined in the local store .HP .BR semanage_fcontext_query "(3)" \- .br query a file context spec in the persistent policy .HP .BR semanage_fcontext_query_local "(3)" \- .br query a file context spec in the local store .HP .BR semanage_fcontext_count "(3)" \- .br count the number of file context specs defined in the persistent policy .HP .BR semanage_fcontext_count_local "(3)" \- .br count the number of file context specs defined in the local store .HP .BR semanage_fcontext_iterate "(3)" \- .br execute a callback for each file context spec in the persistent policy .HP .BR semanage_fcontext_iterate_local "(3)" \- .br execute a callback for each file context spec in the local store .HP .BR semanage_fcontext_list "(3)" \- .br return an array containing all file context specs in the persistent policy .HP .BR semanage_fcontext_list_local "(3)" \- .br return an array containing all file context specs in the local store libsemanage/man/man3/semanage_fcontext_count.30100644 0000000 0000000 00000000032 13756670064 020464 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_fcontext_count_local.30100644 0000000 0000000 00000000032 13756670064 021636 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_fcontext_del_local.30100644 0000000 0000000 00000000030 13756670064 021250 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_fcontext_exists.30100644 0000000 0000000 00000000033 13756670064 020654 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_fcontext_exists_local.30100644 0000000 0000000 00000000033 13756670064 022026 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_fcontext_iterate.30100644 0000000 0000000 00000000034 13756670064 020773 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_fcontext_iterate_local.30100644 0000000 0000000 00000000034 13756670064 022145 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_fcontext_list.30100644 0000000 0000000 00000000031 13756670064 020306 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_fcontext_list_local.30100644 0000000 0000000 00000000031 13756670064 021460 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_fcontext_modify_local.30100644 0000000 0000000 00000000033 13756670064 021776 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_fcontext_query.30100644 0000000 0000000 00000000032 13756670064 020501 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_fcontext_query_local.30100644 0000000 0000000 00000000032 13756670064 021653 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_iface.30100644 0000000 0000000 00000005745 13756670064 016511 0ustar000000000 0000000 .TH semanage_iface 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_iface \- SELinux Network Interfaces Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a network interface. .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_iface_create "(3)" \- .br create an interface .HP .BR semanage_iface_free "(3)" \- .br release resources for this interface .HP .BR semanage_iface_key_create "(3)" \- .br create a key, which can be used to identify an interface .HP .BR semanage_iface_key_free "(3)" \- .br release resources for this interface key .HP .BR semanage_iface_key_extract "(3)" \- .br create a key matching this interface .HP .BR semanage_iface_clone "(3)" \- .br create an identical interface (deep-copy clone) .HP .BR semanage_iface_compare "(3)" \- .br compare this interface to the provided key .HP .BR semanage_iface_compare2 "(3)" \- .br compare this interface to another .SH "Properties API Overview" .HP .BR semanage_iface_get_name "(3)" \- .br return the name of this interface .HP .BR semanage_iface_set_name "(3)" \- .br set the name of this interface .HP .BR semanage_iface_get_ifcon "(3)" \- .br return the SELinux context associated with this interface .HP .BR semanage_iface_set_ifcon "(3)" \- .br set the SELinux context associated with this interface .HP .BR semanage_iface_get_msgcon "(3)" \- .br return the SELinux context associated with packets sent over this interface .HP .BR semanage_iface_set_msgcon "(3)" \- .br set the SELinux context associated with packets sent over this interface .SH "Record Store API Overview" .HP .BR semanage_iface_modify_local "(3)" \- .br add or update an interface in the local store .HP .BR semanage_iface_del_local "(3)" \- .br delete an interface from the local store .HP .BR semanage_iface_exists "(3)" \- .br check if an interface is defined in the persistent policy .HP .BR semanage_iface_exists_local "(3)" \- .br check if an interface is defined in the local store .HP .BR semanage_iface_query "(3)" \- .br query an interface in the persistent policy .HP .BR semanage_iface_query_local "(3)" \- .br query an interface in the local store .HP .BR semanage_iface_count "(3)" \- .br count the number of interfaces defined in the persistent policy .HP .BR semanage_iface_count_local "(3)" \- .br count the number of interfaces defined in the local store .HP .BR semanage_iface_iterate "(3)" \- .br execute a callback for each interface in the persistent policy .HP .BR semanage_iface_iterate_local "(3)" \- .br execute a callback for each interface in the local store .HP .BR semanage_iface_list "(3)" \- .br return an array containing all interfaces in the persistent policy .HP .BR semanage_iface_list_local "(3)" \- .br return an array containing all interfaces in the local store libsemanage/man/man3/semanage_iface_count.30100644 0000000 0000000 00000000032 13756670064 017701 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_iface_count_local.30100644 0000000 0000000 00000000032 13756670064 021053 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_iface_del_local.30100644 0000000 0000000 00000000030 13756670064 020465 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_iface_exists.30100644 0000000 0000000 00000000033 13756670064 020071 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_iface_exists_local.30100644 0000000 0000000 00000000033 13756670064 021243 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_iface_iterate.30100644 0000000 0000000 00000000034 13756670064 020210 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_iface_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021362 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_iface_list.30100644 0000000 0000000 00000000031 13756670064 017523 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_iface_list_local.30100644 0000000 0000000 00000000031 13756670064 020675 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_iface_modify_local.30100644 0000000 0000000 00000000033 13756670064 021213 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_iface_query.30100644 0000000 0000000 00000000032 13756670064 017716 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_iface_query_local.30100644 0000000 0000000 00000000032 13756670064 021070 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_iterate.30100644 0000000 0000000 00000004141 13756670064 017064 0ustar000000000 0000000 .TH semanage_iterate 3 "15 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_iterate \- SELinux Management API .SH "SYNOPSIS" The following iterate function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int ITERATE_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " int (*handler) ( .br .BI " const semanage_OBJECT_t *" object "," .br .BI " void *" varg ")," .br .BI " void *" handler_arg ");" .SH "DESCRIPTION" .TP .B Behavior: The iterate function will execute the specified handler over all objects in the selected location. An arbitrary argument can be passed into the handler function along with each object. The object passed in is property of the libsemanage library, and may not be modified or preserved - use .B semanage_OBJECT_clone if that is necessary. The handler code may not invoke any semanage write requests for the same object type (i.e. modifying the underlying store is not allowed). The iterate function is reentrant only while inside a transaction (see .B semanage_begin_transaction ). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return \-1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I handler is the function to execute, with .I handler_arg as its second parameter, and each object as its first parameter. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ) .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_list.30100644 0000000 0000000 00000002704 13756670064 016405 0ustar000000000 0000000 .TH semanage_list 3 "16 March 2006" "ivg2@cornell.edu" "SELinux managent API documentation" .SH "NAME" semanage_list \- SELinux Lists Management API .SH "SYNOPSIS" The following list function is supported for any SELinux managent record. .br Replace the function and object name as necessary. .B extern int LIST_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " semanage_OBJECT_t ***" objects "," .br .BI " unsigned int* " count ");" .SH "DESCRIPTION" .TP .B Behavior: The list function will return an array of all the objects in the selected location. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The function will allocate and populate the array of objects, and store it at the location pointed by .I objects. It will write the number of objects at the location pointed by .I count. The array, and all its objects become property of the caller. Each object must be freed with .B semanage_OBJECT_free. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ) .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_modify.30100644 0000000 0000000 00000003343 13756670064 016721 0ustar000000000 0000000 .TH semanage_modify 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_modify \- SELinux Management API .SH "SYNOPSIS" The following modify function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int MODIFY_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " const semanage_OBJECT_key_t *" key "," .br .BI " const semanage_OBJECT_t *" data ");" .SH "DESCRIPTION" .TP .B Behavior: If a matching key is found in the local store, the provided object will replace the current one. Otherwise, it will be added to the store. When .BR semanage_commit "(3)" is invoked, changes will be permanently written into the local store, and then loaded into policy. Validity of the object being added is checked at commit time. Adding new objects with respect to policy is allowed, except in the case of booleans. Attempt to add new booleans with respect to policy will fail at commit time. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I key identifies the .I data object, which will be written into the store. The key are data are properties of the caller, and are not stored or modified internally. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ), and must be executed in a transaction (see .BR semanage_begin_transaction "(3)" ). .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise 0 is returned. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_begin_transaction "(3), " semanage_connect "(3), " semanage_commit "(3). " libsemanage/man/man3/semanage_node.30100644 0000000 0000000 00000007323 13756670064 016361 0ustar000000000 0000000 .TH semanage_node 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_node \- SELinux Network Nodes Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a network node. .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_node_create "(3)" \- .br create a node .HP .BR semanage_node_free "(3)" \- .br release resources for this node .HP .BR semanage_node_key_create "(3)" \- .br create a key, which can be used to identify a node .HP .BR semanage_node_key_free "(3)" \- .br release resources for this node key .HP .BR semanage_node_key_extract "(3)" \- .br create a key matching this node .HP .BR semanage_node_clone "(3)" \- .br create an identical node (deep-copy clone) .HP .BR semanage_node_compare "(3)" \- .br compare this node to the provided key .HP .BR semanage_node_compare2 "(3)" \- .br compare this node to another .SH "Properties API Overview" .HP .BR semanage_node_get_addr "(3)" \- .br return the IP address of this node in string representation .HP .BR semanage_node_set_addr "(3)" \- .br set the IP address of this node from the provided string representation and protocol .HP .BR semanage_node_get_addr_bytes "(3)" \- .br return the IP address of this node as a byte array in network byte order .HP .BR semanage_node_set_addr_bytes "(3)" \- .br set the IP address of this node from the provided byte array in network byte order .HP .BR semanage_node_get_mask "(3)" \- .br return the IP mask of this node in string representation .HP .BR semanage_node_set_mask "(3)" \- .br set the IP mask of this node from the provided string representation and protocol version .HP .BR semanage_node_get_mask_bytes "(3)" \- .br return the IP mask of this node as a byte array in network byte order .HP .BR semanage_node_set_mask_bytes "(3)" \- .br set the IP mask of this node from the provided byte array in network byte order .HP .BR semanage_node_get_proto "(3)" \- .br return the IP protocol version for this node .HP .BR semanage_node_get_proto_str "(3)" \- .br return a string representation of the given node protocol .HP .BR semanage_node_set_proto "(3)" \- .br set the IP protocol version for this node .HP .BR semanage_node_get_con "(3)" \- .br return the SELinux context associated with this node .HP .BR semanage_node_set_con "(3)" \- .br set the SELinux context associated with this node .SH "Record Store API Overview" .HP .BR semanage_node_modify_local "(3)" \- .br add or update an interface in the local store .HP .BR semanage_node_del_local "(3)" \- .br delete an interface from the local store .HP .BR semanage_node_exists "(3)" \- .br check if an interface is defined in the persistent policy .HP .BR semanage_node_exists_local "(3)" \- .br check if an interface is defined in the local store .HP .BR semanage_node_query "(3)" \- .br query an interface in the persistent policy .HP .BR semanage_node_query_local "(3)" \- .br query an interface in the local store .HP .BR semanage_node_count "(3)" \- .br count the number of nodes defined in the persistent policy .HP .BR semanage_node_count_local "(3)" \- .br count the number of nodes defined in the local store .HP .BR semanage_node_iterate "(3)" \- .br execute a callback for each interface in the persistent policy .HP .BR semanage_node_iterate_local "(3)" \- .br execute a callback for each interface in the local store .HP .BR semanage_node_list "(3)" \- .br return an array containing all nodes in the persistent policy .HP .BR semanage_node_list_local "(3)" \- .br return an array containing all nodes in the local store libsemanage/man/man3/semanage_node_count.30100644 0000000 0000000 00000000032 13756670064 017557 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_node_count_local.30100644 0000000 0000000 00000000032 13756670064 020731 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_node_del_local.30100644 0000000 0000000 00000000030 13756670064 020343 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_node_exists.30100644 0000000 0000000 00000000033 13756670064 017747 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_node_exists_local.30100644 0000000 0000000 00000000033 13756670064 021121 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_node_iterate.30100644 0000000 0000000 00000000034 13756670064 020066 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_node_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021240 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_node_list.30100644 0000000 0000000 00000000031 13756670064 017401 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_node_list_local.30100644 0000000 0000000 00000000031 13756670064 020553 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_node_modify_local.30100644 0000000 0000000 00000000033 13756670064 021071 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_node_query.30100644 0000000 0000000 00000000032 13756670064 017574 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_node_query_local.30100644 0000000 0000000 00000000032 13756670064 020746 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_port.30100644 0000000 0000000 00000006271 13756670064 016421 0ustar000000000 0000000 .TH semanage_port 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_port \- SELinux Network Ports Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a range of network ports. .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_port_create "(3)" \- .br create a port range .HP .BR semanage_port_free "(3)" \- .br release resources for this port range .HP .BR semanage_port_key_create "(3)" \- .br create a key, which can be used to identify a port range .HP .BR semanage_port_key_free "(3)" \- .br release resources for this port range key .HP .BR semanage_port_key_extract "(3)" \- .br create a key matching this port range .HP .BR semanage_port_clone "(3)" \- .br create an identical port range (deep-copy clone) .HP .BR semanage_port_compare "(3)" \- .br compare this port range to the provided key .HP .BR semanage_port_compare2 "(3)" \- .br compare this port range to another .SH "Properties API Overview" .HP .BR semanage_port_get_proto "(3)" \- .br return the protocol for this port range .HP .BR semanage_port_get_proto_str "(3)" \- .br return a string representation of the given port protocol .HP .BR semanage_port_set_proto "(3)" \- .br set the protocol for this port range .HP .BR semanage_port_get_low "(3)" \- .br return the low port number for this port range .HP .BR semanage_port_get_high "(3)" \- .br return the high port number for this port range .HP .BR semanage_port_set_port "(3)" \- .br set the port number (same low and high) for this port range .HP .BR semanage_port_set_range "(3)" \- .br set the low and high port number for this port range .HP .BR semanage_port_get_con "(3)" \- .br return the SELinux context for this port range .HP .BR semanage_port_set_con "(3)" \- .br set the SELinux context for this port range .SH "Record Store API Overview" .HP .BR semanage_port_modify_local "(3)" \- .br add or update a port range in the local store .HP .BR semanage_port_del_local "(3)" \- .br delete a port range from the local store .HP .BR semanage_port_exists "(3)" \- .br check if a port range is defined in the persistent policy .HP .BR semanage_port_exists_local "(3)" \- .br check if a port range is defined in the local store .HP .BR semanage_port_query "(3)" \- .br query a port range in the persistent policy .HP .BR semanage_port_query_local "(3)" \- .br query a port range in the local store .HP .BR semanage_port_count "(3)" \- .br count the number of port ranges defined in the persistent policy .HP .BR semanage_port_count_local "(3)" \- .br count the number of port ranges defined in the local store .HP .BR semanage_port_iterate "(3)" \- .br execute a callback for each port range in the persistent policy .HP .BR semanage_port_iterate_local "(3)" \- .br execute a callback for each port range in the local store .HP .BR semanage_port_list "(3)" \- .br return an array containing all port ranges in the persistent policy .HP .BR semanage_port_list_local "(3)" \- .br return an array containing all port ranges in the local store libsemanage/man/man3/semanage_port_count.30100644 0000000 0000000 00000000032 13756670064 017616 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_port_count_local.30100644 0000000 0000000 00000000032 13756670064 020770 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_port_del_local.30100644 0000000 0000000 00000000030 13756670064 020402 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_port_exists.30100644 0000000 0000000 00000000033 13756670064 020006 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_port_exists_local.30100644 0000000 0000000 00000000033 13756670064 021160 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_port_iterate.30100644 0000000 0000000 00000000034 13756670064 020125 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_port_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021277 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_port_list.30100644 0000000 0000000 00000000031 13756670064 017440 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_port_list_local.30100644 0000000 0000000 00000000031 13756670064 020612 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_port_modify_local.30100644 0000000 0000000 00000000033 13756670064 021130 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_port_query.30100644 0000000 0000000 00000000032 13756670064 017633 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_port_query_local.30100644 0000000 0000000 00000000032 13756670064 021005 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_query.30100644 0000000 0000000 00000002722 13756670064 016577 0ustar000000000 0000000 .TH semanage_query 3 "15 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_query \- SELinux Management API .SH "SYNOPSIS" The following query function is supported for any semanage record. .br Replace the function and object name as necessary. .B extern int QUERY_FUNCTION ( .br .BI " semanage_handle_t *" handle "," .br .BI " const semanage_OBJECT_key_t *" key "," .br .BI " semanage_OBJECT_t **" response ");" .SH "DESCRIPTION" .TP .B Behavior: The query function will fail if a matching key is not found. Otherwise, the corresponding object is returned. .TP .B Parameters: The .I handle is used to track persistent state across semanage calls, and for error reporting. The .I key identifies the object being queried, which will be stored in the address pointed by .I response The key is a property of the caller, and will not be stored or modified internally. The object returned becomes a property of the caller, and must be freed with .B semanage_OBJECT_free. .TP .B Requirements: This function requires an semanage connection to be established (see .BR semanage_connect "(3)" ) .SH "RETURN VALUE" In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_set_root.30100644 0000000 0000000 00000001506 13756670064 017267 0ustar000000000 0000000 .TH semanage_set_root 3 "1 June 2011" "dwalsh@redhat.com" "Libsemanage API documentation" .SH "NAME" semanage_set_root, semanage_root \- SELinux Management API .SH "SYNOPSIS" Set/get the alternate root directory for SELinux configuration directory. .B #include .B extern int semanage_set_root(const char *path); .B extern const char *semanage_root(void); .SH "DESCRIPTION" .TP The function semanage_set_root() sets an alternate root directory for SELinux configuration paths to be used by the semanage library. .SH "RETURN VALUE" The function semanage_set_root() returns \-1 in case of failure. Otherwise, 0 is returned. The function semanage_root() returns the semanage root. The returned value should not be modified by the caller. .SH "SEE ALSO" .BR semanage_handle_create "(3), " semanage_connect "(3), " libsemanage/man/man3/semanage_seuser.30100644 0000000 0000000 00000006051 13756670064 016737 0ustar000000000 0000000 .TH semanage_seuser 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_seuser \- Linux UID to SELinux User Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a Unix user. Typically many Unix users are mapped to the same SELinux user. See .BR semanage_user "(3)" for overview of the SELinux user API. .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_seuser_create "(3)" \- .br create a seuser .HP .BR semanage_seuser_free "(3)" \- .br release resources for this seuser .HP .BR semanage_seuser_key_create "(3)" \- .br create a key, which can be used to identify a seuser .HP .BR semanage_seuser_key_free "(3)" \- .br release resources for this seuser key .HP .BR semanage_seuser_key_extract "(3)" \- .br create a key matching this seuser .HP .BR semanage_seuser_clone "(3)" \- .br create an identical seuser (deep-copy clone) .HP .BR semanage_seuser_compare "(3)" \- .br compare this seuser to the provided key .HP .BR semanage_seuser_compare2 "(3)" \- .br compare this seuser to another .SH "Properties API Overview" .HP .BR semanage_seuser_get_name "(3)" \- .br return the name of this seuser .HP .BR semanage_user_set_name "(3)" \- .br set the name of this seuser .HP .BR semanage_seuser_get_sename "(3)" \- .br return the name of the (SELinux) user mapped to this seuser .HP .BR semanage_user_set_sename "(3)" \- .br set the name of the (SELinux) user mapped to this seuser .HP .BR semanage_user_get_mlsrange "(3)" \- .br return a the range of valid MLS sensitivities and categories for this user .HP .BR semanage_user_set_mlsrange "(3)" \- .br set the range of valid MLS sensitivities and categories for this user .SH "Record Store API Overview" .HP .BR semanage_seuser_modify_local "(3)" \- .br add or update a seuser in the local store .HP .BR semanage_seuser_del_local "(3)" \- .br delete a seuser from the local store .HP .BR semanage_seuser_exists "(3)" \- .br check if a seuser is defined in the persistent policy .HP .BR semanage_seuser_exists_local "(3)" \- .br check if a seuser is defined in the local store .HP .BR semanage_seuser_query "(3)" \- .br query a seuser in the persistent policy .HP .BR semanage_seuser_query_local "(3)" \- .br query a seuser in the local store .HP .BR semanage_seuser_count "(3)" \- .br count the number of seusers defined in the persistent policy .HP .BR semanage_seuser_count_local "(3)" \- .br count the number of seusers defined in the local store .HP .BR semanage_seuser_iterate "(3)" \- .br execute a callback for each seuser in the persistent policy .HP .BR semanage_seuser_iterate_local "(3)" \- .br execute a callback for each seuser in the local store .HP .BR semanage_seuser_list "(3)" \- .br return an array containing all seusers in the persistent policy .HP .BR semanage_seuser_list_local "(3)" \- .br return an array containing all seusers in the local store libsemanage/man/man3/semanage_seuser_count.30100644 0000000 0000000 00000000032 13756670064 020140 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_seuser_count_local.30100644 0000000 0000000 00000000032 13756670064 021312 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_seuser_del_local.30100644 0000000 0000000 00000000030 13756670064 020724 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_seuser_exists.30100644 0000000 0000000 00000000033 13756670064 020330 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_seuser_exists_local.30100644 0000000 0000000 00000000033 13756670064 021502 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_seuser_iterate.30100644 0000000 0000000 00000000034 13756670064 020447 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_seuser_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021621 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_seuser_list.30100644 0000000 0000000 00000000031 13756670064 017762 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_seuser_list_local.30100644 0000000 0000000 00000000031 13756670064 021134 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_seuser_modify_local.30100644 0000000 0000000 00000000033 13756670064 021452 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_seuser_query.30100644 0000000 0000000 00000000032 13756670064 020155 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_seuser_query_local.30100644 0000000 0000000 00000000032 13756670064 021327 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_user.30100644 0000000 0000000 00000007242 13756670064 016412 0ustar000000000 0000000 .TH semanage_user 3 "16 March 2006" "ivg2@cornell.edu" "Libsemanage API documentation" .SH "NAME" semanage_user \- SELinux User Management API .SH "SYNOPSIS" .B #include .br .B #include .br .B #include .PP This object contains properties associated with a SELinux user. Typically many Unix users are mapped to the same SELinux user. See .BR semanage_seuser "(3)" for overview of the Unix user API. .PP For details on a specific function, see its manual page. .SH "Record API Overview" .HP .BR semanage_user_create "(3)" \- .br create a user .HP .BR semanage_user_free "(3)" \- .br release resources for this user .HP .BR semanage_user_key_create "(3)" \- .br create a key, which can be used to identify a user .HP .BR semanage_user_key_free "(3)" \- .br release resources for this user key .HP .BR semanage_user_key_extract "(3)" \- .br create a key matching this user .HP .BR semanage_user_clone "(3)" \- .br create an identical user (deep-copy clone) .HP .BR semanage_user_compare "(3)" \- .br compare this user to the provided key .HP .BR semanage_user_compare2 "(3)" \- .br compare this user to another .SH "Properties API Overview" .HP .BR semanage_user_get_name "(3)" \- .br return the name of this user .HP .BR semanage_user_set_name "(3)" \- .br set the name of this user .HP .BR semanage_user_get_prefix "(3)" \- .br return the labeling prefix for this user, used to control the contexts of user directories .HP .BR semanage_user_set_prefix "(3)" \- .br set the labeling prefix for this user .HP .BR semanage_user_get_mlslevel "(3)" \- .br return the default MLS level, which is assigned to this user at login time .HP .BR semanage_user_set_mlslevel "(3)" \- .br set the default MLS level .HP .BR semanage_user_get_mlsrange "(3)" \- .br return the range of valid MLS sensitivities and categories for this user .HP .BR semanage_user_set_mlsrange "(3)" \- .br set the range of valid MLS sensitivities and categories for this user .HP .BR semanage_user_add_role "(3)" \- .br add a role to the user's list of valid roles .HP .BR semanage_user_del_role "(3)" \- .br remove a role from the user's list of valid roles .HP .BR semanage_user_has_role "(3)" \- .br check if a role is valid for this user .HP .BR semanage_user_get_num_roles "(3)" \- .br return the number of valid roles for this user .HP .BR semanage_user_get_roles "(3)" \- .br return an array containing the roles for this user .HP .BR semanage_user_set_roles "(3)" \- set the roles for this user .SH "Record Store API Overview" .HP .BR semanage_user_modify_local "(3)" \- .br add or update a user in the local store .HP .BR semanage_user_del_local "(3)" \- .br delete a user from the local store .HP .BR semanage_user_exists "(3)" \- .br check if a user is defined in the persistent policy .HP .BR semanage_user_exists_local "(3)" \- .br check if a user is defined in the local store .HP .BR semanage_user_query "(3)" \- .br query a user in the persistent policy .HP .BR semanage_user_query_local "(3)" \- .br query a user in the local store .HP .BR semanage_user_count "(3)" \- .br count the number of users defined in the persistent policy .HP .BR semanage_user_count_local "(3)" \- .br count the number of users defined in the local store .HP .BR semanage_user_iterate "(3)" \- .br execute a callback for each user in the persistent policy .HP .BR semanage_user_iterate_local "(3)" \- .br execute a callback for each user in the local store .HP .BR semanage_user_list "(3)" \- .br return an array containing all users in the persistent policy .HP .BR semanage_user_list_local "(3)" \- .br return an array containing all users in the local store libsemanage/man/man3/semanage_user_count.30100644 0000000 0000000 00000000032 13756670064 017610 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_user_count_local.30100644 0000000 0000000 00000000032 13756670064 020762 0ustar000000000 0000000 .so man3/semanage_count.3 libsemanage/man/man3/semanage_user_del_local.30100644 0000000 0000000 00000000030 13756670064 020374 0ustar000000000 0000000 .so man3/semanage_del.3 libsemanage/man/man3/semanage_user_exists.30100644 0000000 0000000 00000000033 13756670064 020000 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_user_exists_local.30100644 0000000 0000000 00000000033 13756670064 021152 0ustar000000000 0000000 .so man3/semanage_exists.3 libsemanage/man/man3/semanage_user_iterate.30100644 0000000 0000000 00000000034 13756670064 020117 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_user_iterate_local.30100644 0000000 0000000 00000000034 13756670064 021271 0ustar000000000 0000000 .so man3/semanage_iterate.3 libsemanage/man/man3/semanage_user_list.30100644 0000000 0000000 00000000031 13756670064 017432 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_user_list_local.30100644 0000000 0000000 00000000031 13756670064 020604 0ustar000000000 0000000 .so man3/semanage_list.3 libsemanage/man/man3/semanage_user_modify_local.30100644 0000000 0000000 00000000033 13756670064 021122 0ustar000000000 0000000 .so man3/semanage_modify.3 libsemanage/man/man3/semanage_user_query.30100644 0000000 0000000 00000000032 13756670064 017625 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man3/semanage_user_query_local.30100644 0000000 0000000 00000000032 13756670064 020777 0ustar000000000 0000000 .so man3/semanage_query.3 libsemanage/man/man5/0040755 0000000 0000000 00000000000 13756670064 013510 5ustar000000000 0000000 libsemanage/man/man5/semanage.conf.50100644 0000000 0000000 00000012275 13756670064 016306 0ustar000000000 0000000 .TH semanage.conf "5" "September 2011" "semanage.conf" "Linux System Administration" .SH NAME semanage.conf \- global configuration file for the SELinux Management library .SH DESCRIPTION .PP The .BR semanage.conf file is usually located under the directory /etc/selinux and it is used for run-time configuration of the behavior of the SELinux Management library. .PP Each line should contain a configuration parameter followed by the equal sign ("=") and then followed by the configuration value for that parameter. Anything after the "#" symbol is ignored similarly to empty lines. .PP The following parameters are allowed: .RS .TP .B module-store Specify how the SELinux Management library should interact with the SELinux policy store. When set to "direct", the SELinux Management library writes to the SELinux policy module store directly (this is the default setting). Otherwise a socket path or a server name can be used for the argument. If the argument begins with "/" (as in "/foo/bar"), it represents the path to a named socket that should be used to connect the policy management server. If the argument does not begin with a "/" (as in "foo.com:4242"), it should be interpreted as the name of a remote policy management server to be used through a TCP connection (default port is 4242 unless a different one is specified after the server name using the colon to separate the two fields). .TP .B root Specify an alternative root path to use for the store. The default is "/" .TP .B store-root Specify an alternative store_root path to use. The default is "/var/lib/selinux" .TP .B compiler-directory Specify an alternative directory that contains HLL to CIL compilers. The default value is "/usr/libexec/selinux/hll". .TP .B ignore-module-cache Whether or not to ignore the cache of CIL modules compiled from HLL. It can be set to either "true" or "false" and is set to "false" by default. If the cache is ignored, then all CIL modules are recompiled from their HLL modules. .TP .B policy-version When generating the policy, by default .BR semanage will set the policy version to POLICYDB_VERSION_MAX, as defined in . Change this setting if a different version needs to be set for the policy. .TP .B target-platform The target platform to generate policies for. Valid values are "selinux" and "xen", and is set to "selinux" by default. .TP .B expand-check Whether or not to check "neverallow" rules when executing all .BR semanage command. It can be set to either "0" (disabled) or "1" (enabled) and by default it is enabled. There might be a large penalty in execution time if this option is enabled. .TP .B file-mode By default the permission mode for the run-time policy files is set to 0644. .TP .B save-previous It controls whether the previous module directory is saved after a successful commit to the policy store and it can be set to either "true" or "false". By default it is set to "false" (the previous version is deleted). .TP .B save-linked It controls whether the previously linked module is saved (with name "base.linked") after a successful commit to the policy store. It can be set to either "true" or "false" and by default it is set to "false" (the previous module is deleted). .TP .B ignoredirs List, separated by ";", of directories to ignore when setting up users homedirs. Some distributions use this to stop labeling /root as a homedir. .TP .B usepasswd Whether or not to enable the use getpwent() to obtain a list of home directories to label. It can be set to either "true" or "false". By default it is set to "true". .TP .B disable-genhomedircon It controls whether or not the genhomedircon function is executed when using the .BR semanage command and it can be set to either "false" or "true". By default the genhomedircon functionality is enabled (equivalent to this option set to "false"). .TP .B handle-unknown This option controls the kernel behavior for handling permissions defined in the kernel but missing from the actual policy. It can be set to "deny", "reject" or "allow". .TP .B bzip-blocksize It should be in the range 0-9. A value of 0 means no compression. By default the bzip block size is set to 9 (actual block size value is obtained after multiplication by 100000). .TP .B bzip-small When set to "true", the bzip algorithm shall try to reduce its system memory usage. It can be set to either "true" or "false" and by default it is set to "false". .TP .B remove-hll When set to "true", HLL files will be removed after compilation into CIL. In order to delete HLL files already compiled into CIL, modules will need to be recompiled with the .BR ignore-module-cache option set to 'true' or using the .BR ignore-module-cache option with semodule. The remove-hll option can be set to either "true" or "false" and by default it is set to "false". Please note that since this option deletes all HLL files, an updated HLL compiler will not be able to recompile the original HLL file into CIL. In order to compile the original HLL file into CIL, the same HLL file will need to be reinstalled. .SH "SEE ALSO" .TP semanage(8) .PP .SH AUTHOR This manual page was written by Guido Trentalancia . The SELinux management library was written by Tresys Technology LLC and Red Hat Inc. libsemanage/man/ru/0040755 0000000 0000000 00000000000 13756670064 013276 5ustar000000000 0000000 libsemanage/man/ru/man5/0040755 0000000 0000000 00000000000 13756670064 014136 5ustar000000000 0000000 libsemanage/man/ru/man5/semanage.conf.50100644 0000000 0000000 00000023062 13756670064 016730 0ustar000000000 0000000 .TH semanage.conf "5" "Сентябрь 2011" "semanage.conf" "Администрирование системы Linux" .SH ИМЯ semanage.conf \- глобальный файл конфигурации для библиотеки управления SELinux .SH ОПИСАНИЕ .PP Файл .BR semanage.conf обычно располагается в каталоге /etc/selinux и используется для конфигурации поведения библиотеки управления SELinux в среде выполнения. .PP Каждая строка должна содержать параметр конфигурации, за которым следует знак равенства ("=") и значение конфигурации этого параметра. Все символы, которые следуют за "#", игнорируются (аналогично пустым строкам). .PP Разрешены следующие параметры: .RS .TP .B module-store Указать, как библиотека управления SELinux должна взаимодействовать с хранилищем политики SELinux. Если установлено "direct", библиотека управления SELinux выполняет запись напрямую в хранилище модулей политики SELinux (это значение по умолчанию). В ином случае в качестве аргумента может использоваться путь к сокету или имя сервера. Если аргумент начинается с "/" (как в "/foo/bar"), он представляет собой путь к именованному сокету, который следует использовать для подключения сервера управления политикой. Если аргумент не начинается с "/" (как в "foo.com:4242"), он должен интерпретироваться как имя удалённого сервера управления политикой, который следует использовать через TCP-подключение (порт по умолчанию 4242, если только после имени сервера через двоеточие, разделяющее два поля, не указан другой порт). .TP .B root Указать альтернативный корневой путь к хранилищу. По умолчанию: "/" .TP .B store-root Указать альтернативный путь store_root. По умолчанию: "/var/lib/selinux" .TP .B compiler-directory Указать альтернативный каталог, который содержит компиляторы HLL в CIL. Значение по умолчанию: "/usr/libexec/selinux/hll". .TP .B ignore-module-cache Определяет, следует ли игнорировать кэш модулей CIL, скомпилированных из HLL. Можно установить либо значение "true", либо значение "false" (по умолчанию установлено "false"). Если кэш игнорируется, все модули CIL перекомпилируются из соответствующих модулей HLL. .TP .B policy-version При создании политики .BR semanage по умолчанию устанавливает версию политики POLICYDB_VERSION_MAX, как определено в . Измените этот параметр, если для политики требуется установить другую версию. .TP .B target-platform Целевая платформа, для которой создаются политики. Действительными значениями являются "selinux" и "xen" (по умолчанию установлено "selinux"). .TP .B expand-check Определяет, следует ли проверять правила "neverallow" при исполнении всех команд .BR semanage. Для этого параметра можно установить либо значение "0" (отключён), либо "1" (включён). По умолчанию параметр включён. Время выполнения может сильно возрасти, если этот параметр включён. .TP .B file-mode По умолчанию для разрешительного режима для файлов среды выполнения политики установлено значение 0644. .TP .B save-previous Определяет, следует ли сохранять прежний каталог модуля после успешной фиксации модуля в хранилище политики. Для параметра можно установить либо значение "true", либо значение "false". По умолчанию установлено "false" (прежняя версия удаляется). .TP .B save-linked Определяет, следует ли сохранять прежний связанный модуль (с именем "base.linked") после успешной фиксации модуля в хранилище политики. Для параметра можно установить либо значение "true", либо значение "false". По умолчанию установлено "false" (прежний модуль удаляется). .TP .B ignoredirs Разделённый ";" список каталогов, которые следует игнорировать при установке домашних каталогов пользователей. В некоторых дистрибутивах этот параметр используется для того, чтобы /root не отмечался как домашний каталог. .TP .B usepasswd Определяет, использовать ли getpwent(), чтобы получить список домашних каталогов, для которых следует проставить метки. Для параметра можно установить либо значение "true", либо значение "false" (по умолчанию установлено "true"). .TP .B disable-genhomedircon Определяет, следует ли исполнять функцию genhomedircon при использовании команды .BR semanage. Для параметра можно установить либо значение "true", либо значение "false". По умолчанию возможность genhomedircon включена (эквивалентно установке значения "false" для этого параметра). .TP .B handle-unknown Этот параметр управляет тем, как ядро обрабатывает разрешения, которые определены в ядре, но отсутствуют в фактической политике. Возможные значения: "deny", "reject" или "allow". .TP .B bzip-blocksize Этот параметр должен находиться в диапазоне 0-9. Значение 0 означает отсутствие сжатия. По умолчанию значение размера блока bzip равняется 9 (фактическое значение размера блока получается путём умножения на 100000). .TP .B bzip-small Если для этого параметра установлено значение "true", алгоритм bzip попытается уменьшить использование системной памяти. Также для этого параметра можно установить значение "false" (по умолчанию установлено это значение). .TP .B remove-hll Если для этого параметра установлено значение "true", файлы HLL будут удалены после компиляции в CIL. Чтобы удалить уже cкомпилированные в CIL файлы HLL, необходимо перекомпилировать модули, установив для параметра .BR ignore-module-cache значение "true", или используя параметр .BR ignore-module-cache с semodule. Для параметра remove-hll можно установить либо значение "true", либо значение "false" (по умолчанию установлено "false"). Обратите внимание: так как этот параметр удаляет все файлы HLL, обновлённый компилятор HLL не сможет перекомпилировать исходный файл HLL в CIL. Чтобы скомпилировать исходный файл HLL в CIL, необходимо переустановить этот файл HLL. .SH "СМОТРИТЕ ТАКЖЕ" .TP semanage(8) .PP .SH АВТОРЫ Эта страница руководства была написана Guido Trentalancia . Библиотека управления SELinux была написана Tresys Technology LLC и Red Hat Inc. Перевод на русский язык выполнила Герасименко Олеся . libsemanage/src/0040755 0000000 0000000 00000000000 13756670064 012664 5ustar000000000 0000000 libsemanage/src/.gitignore0100644 0000000 0000000 00000000131 13756670064 014644 0ustar000000000 0000000 semanageswig_wrap.c semanageswig_python_exception.i semanage.py semanageswig_ruby_wrap.c libsemanage/src/Makefile0100644 0000000 0000000 00000013003 13756670064 014316 0ustar000000000 0000000 # Support building the Python bindings multiple times, against various Python # runtimes (e.g. Python 2 vs Python 3) by optionally prefixing the build # targets with "PYPREFIX": PYTHON ?= python3 PYPREFIX ?= $(shell $(PYTHON) -c 'import sys;print("python-%d.%d" % sys.version_info[:2])') RUBY ?= ruby RUBYPREFIX ?= $(notdir $(RUBY)) PKG_CONFIG ?= pkg-config # Installation directories. PREFIX ?= /usr LIBDIR ?= $(PREFIX)/lib INCLUDEDIR ?= $(PREFIX)/include PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX)) PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX)) PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))") PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])') RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]') RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]') RUBYINSTALL ?= $(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]') DEFAULT_SEMANAGE_CONF_LOCATION=/etc/selinux/semanage.conf ifeq ($(DEBUG),1) export CFLAGS = -g3 -O0 -gdwarf-2 -fno-strict-aliasing -Wall -Wshadow -Werror export LDFLAGS = -g endif LEX = flex LFLAGS = -s YACC = bison YFLAGS = -d VERSION = $(shell cat ../VERSION) LIBVERSION = 1 LIBA=libsemanage.a TARGET=libsemanage.so LIBPC=libsemanage.pc SWIGIF= semanageswig_python.i semanageswig_python_exception.i SWIGRUBYIF= semanageswig_ruby.i SWIGCOUT= semanageswig_wrap.c SWIGRUBYCOUT= semanageswig_ruby_wrap.c SWIGLOBJ:= $(patsubst %.c,$(PYPREFIX)%.lo,$(SWIGCOUT)) SWIGRUBYLOBJ:= $(patsubst %.c,$(RUBYPREFIX)%.lo,$(SWIGRUBYCOUT)) SWIGSO=$(PYPREFIX)_semanage.so SWIGFILES=$(SWIGSO) semanage.py SWIGRUBYSO=$(RUBYPREFIX)_semanage.so LIBSO=$(TARGET).$(LIBVERSION) GENERATED=$(SWIGCOUT) $(SWIGRUBYCOUT) semanageswig_python_exception.i $(sort $(wildcard conf-*.[ch])) SRCS= $(filter-out $(GENERATED),$(sort $(wildcard *.c))) OBJS= $(patsubst %.c,%.o,$(SRCS)) conf-scan.o conf-parse.o LOBJS= $(patsubst %.c,%.lo,$(SRCS)) conf-scan.lo conf-parse.lo CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-noreturn -Wmissing-format-attribute SWIG_CFLAGS += -Wno-error -Wno-unused-but-set-variable -Wno-unused-variable -Wno-shadow \ -Wno-unused-parameter override CFLAGS += -I../include -D_GNU_SOURCE RANLIB ?= ranlib SWIG = swig -Wall -python -o $(SWIGCOUT) -outdir ./ SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ all: $(LIBA) $(LIBSO) $(LIBPC) pywrap: all $(SWIGSO) rubywrap: all $(SWIGRUBYSO) $(SWIGLOBJ): $(SWIGCOUT) $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(PYINC) -fPIC -DSHARED -c -o $@ $< $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< $(SWIGSO): $(SWIGLOBJ) $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $< -lsemanage $(PYLIBS) $(SWIGRUBYSO): $(SWIGRUBYLOBJ) $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $^ -lsemanage $(RUBYLIBS) $(LIBA): $(OBJS) $(AR) rcs $@ $^ $(RANLIB) $@ $(LIBSO): $(LOBJS) $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -laudit -lselinux -lbz2 -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBDIR):; s:@includedir@:$(INCLUDEDIR):' < $< > $@ semanageswig_python_exception.i: ../include/semanage/semanage.h bash -e exception.sh > $@ || (rm -f $@ ; false) conf-scan.c: conf-scan.l conf-parse.h $(LEX) $(LFLAGS) -o $@ $< conf-parse.c: conf-parse.y $(YACC) $(YFLAGS) -o $@ $< conf-parse.h: conf-parse.c %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< %.lo: %.c $(CC) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< conf-parse.o: conf-parse.c $(CC) $(filter-out -Werror, $(CFLAGS)) -c -o $@ $< conf-parse.lo: conf-parse.c $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< conf-scan.o: conf-scan.c $(CC) $(filter-out -Werror, $(CFLAGS)) -c -o $@ $< conf-scan.lo: conf-scan.c $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< $(SWIGCOUT): $(SWIGIF) $(SWIG) $< $(SWIGRUBYCOUT): $(SWIGRUBYIF) $(SWIGRUBY) $< swigify: $(SWIGIF) $(SWIG) $< install: all test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR) install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR) install -m 755 $(LIBSO) $(DESTDIR)$(LIBDIR) test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig test -f $(DESTDIR)$(DEFAULT_SEMANAGE_CONF_LOCATION) || install -m 644 -D semanage.conf $(DESTDIR)$(DEFAULT_SEMANAGE_CONF_LOCATION) cd $(DESTDIR)$(LIBDIR) && ln -sf $(LIBSO) $(TARGET) install-pywrap: pywrap test -d $(DESTDIR)$(PYTHONLIBDIR) || install -m 755 -d $(DESTDIR)$(PYTHONLIBDIR) install -m 755 $(SWIGSO) $(DESTDIR)$(PYTHONLIBDIR)/_semanage$(PYCEXT) install -m 644 semanage.py $(DESTDIR)$(PYTHONLIBDIR) install-rubywrap: rubywrap test -d $(DESTDIR)$(RUBYINSTALL) || install -m 755 -d $(DESTDIR)$(RUBYINSTALL) install -m 755 $(SWIGRUBYSO) $(DESTDIR)$(RUBYINSTALL)/semanage.so relabel: /sbin/restorecon $(DESTDIR)$(LIBDIR)/$(LIBSO) clean: -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(SWIGLOBJ) $(SWIGSO) $(SWIGRUBYSO) $(TARGET) conf-parse.c conf-parse.h conf-scan.c *.o *.lo *~ distclean: clean rm -f $(GENERATED) $(SWIGFILES) indent: ../../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch])) .PHONY: all clean pywrap rubywrap swigify install install-pywrap install-rubywrap distclean libsemanage/src/boolean_internal.h0100644 0000000 0000000 00000002513 13756670064 016346 0ustar000000000 0000000 #ifndef _SEMANAGE_BOOLEAN_INTERNAL_H_ #define _SEMANAGE_BOOLEAN_INTERNAL_H_ #include #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_bool_clone) hidden_proto(semanage_bool_compare) hidden_proto(semanage_bool_compare2) hidden_proto(semanage_bool_create) hidden_proto(semanage_bool_free) hidden_proto(semanage_bool_get_name) hidden_proto(semanage_bool_get_value) hidden_proto(semanage_bool_key_extract) hidden_proto(semanage_bool_key_free) hidden_proto(semanage_bool_set_name) hidden_proto(semanage_bool_set_value) /* BOOL RECORD: metod table */ extern record_table_t SEMANAGE_BOOL_RTABLE; extern int bool_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void bool_file_dbase_release(dbase_config_t * dconfig); extern int bool_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void bool_policydb_dbase_release(dbase_config_t * dconfig); extern int bool_activedb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void bool_activedb_dbase_release(dbase_config_t * dconfig); #endif libsemanage/src/boolean_record.c0100644 0000000 0000000 00000010234 13756670064 016002 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_bool_t (Policy Boolean) * Object: semanage_bool_key_t (Policy Boolean Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include #include #include "handle_internal.h" typedef sepol_bool_t semanage_bool_t; typedef sepol_bool_key_t semanage_bool_key_t; #define _SEMANAGE_BOOL_DEFINED_ typedef semanage_bool_t record_t; typedef semanage_bool_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "boolean_internal.h" #include "handle.h" #include "database.h" #include #include /* Key */ int semanage_bool_key_create(semanage_handle_t * handle, const char *name, semanage_bool_key_t ** key) { return sepol_bool_key_create(handle->sepolh, name, key); } int semanage_bool_key_extract(semanage_handle_t * handle, const semanage_bool_t * boolean, semanage_bool_key_t ** key) { return sepol_bool_key_extract(handle->sepolh, boolean, key); } hidden_def(semanage_bool_key_extract) void semanage_bool_key_free(semanage_bool_key_t * key) { sepol_bool_key_free(key); } hidden_def(semanage_bool_key_free) int semanage_bool_compare(const semanage_bool_t * boolean, const semanage_bool_key_t * key) { return sepol_bool_compare(boolean, key); } hidden_def(semanage_bool_compare) int semanage_bool_compare2(const semanage_bool_t * boolean, const semanage_bool_t * boolean2) { return sepol_bool_compare2(boolean, boolean2); } hidden_def(semanage_bool_compare2) static int semanage_bool_compare2_qsort(const semanage_bool_t ** boolean, const semanage_bool_t ** boolean2) { return sepol_bool_compare2(*boolean, *boolean2); } /* Name */ const char *semanage_bool_get_name(const semanage_bool_t * boolean) { return sepol_bool_get_name(boolean); } hidden_def(semanage_bool_get_name) int semanage_bool_set_name(semanage_handle_t * handle, semanage_bool_t * boolean, const char *name) { int rc = -1; const char *prefix = semanage_root(); const char *storename = handle->conf->store_path; const char *selinux_root = selinux_policy_root(); char *oldroot; char *olddir; char *subname = NULL; char *newroot = NULL; char *end; if (!selinux_root) return -1; oldroot = strdup(selinux_root); if (!oldroot) return -1; olddir = strdup(oldroot); if (!olddir) goto out; end = strrchr(olddir, '/'); if (!end) goto out; end++; *end = '\0'; rc = asprintf(&newroot, "%s%s%s", prefix, olddir, storename); if (rc < 0) goto out; if (strcmp(oldroot, newroot)) { rc = selinux_set_policy_root(newroot); if (rc) goto out; } subname = selinux_boolean_sub(name); if (!subname) { rc = -1; goto out; } if (strcmp(oldroot, newroot)) { rc = selinux_set_policy_root(oldroot); if (rc) goto out; } rc = sepol_bool_set_name(handle->sepolh, boolean, subname); out: free(subname); free(oldroot); free(olddir); free(newroot); return rc; } hidden_def(semanage_bool_set_name) /* Value */ int semanage_bool_get_value(const semanage_bool_t * boolean) { return sepol_bool_get_value(boolean); } hidden_def(semanage_bool_get_value) void semanage_bool_set_value(semanage_bool_t * boolean, int value) { sepol_bool_set_value(boolean, value); } hidden_def(semanage_bool_set_value) /* Create/Clone/Destroy */ int semanage_bool_create(semanage_handle_t * handle, semanage_bool_t ** bool_ptr) { return sepol_bool_create(handle->sepolh, bool_ptr); } hidden_def(semanage_bool_create) int semanage_bool_clone(semanage_handle_t * handle, const semanage_bool_t * boolean, semanage_bool_t ** bool_ptr) { return sepol_bool_clone(handle->sepolh, boolean, bool_ptr); } hidden_def(semanage_bool_clone) void semanage_bool_free(semanage_bool_t * boolean) { sepol_bool_free(boolean); } hidden_def(semanage_bool_free) /* Record base functions */ record_table_t SEMANAGE_BOOL_RTABLE = { .create = semanage_bool_create, .key_extract = semanage_bool_key_extract, .key_free = semanage_bool_key_free, .clone = semanage_bool_clone, .compare = semanage_bool_compare, .compare2 = semanage_bool_compare2, .compare2_qsort = semanage_bool_compare2_qsort, .free = semanage_bool_free, }; libsemanage/src/booleans_active.c0100644 0000000 0000000 00000003337 13756670064 016170 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool_key record_key_t; typedef struct semanage_bool record_t; #define DBASE_RECORD_DEFINED #include "boolean_internal.h" #include "handle.h" #include "database.h" int semanage_bool_set_active(semanage_handle_t * handle, const semanage_bool_key_t * key, const semanage_bool_t * data) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_set(handle, dconfig, key, data); } int semanage_bool_query_active(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_query(handle, dconfig, key, response); } int semanage_bool_exists_active(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_bool_count_active(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_count(handle, dconfig, response); } int semanage_bool_iterate_active(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_bool_list_active(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_bool_dbase_active(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/booleans_activedb.c0100644 0000000 0000000 00000007162 13756670064 016476 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool record_t; typedef struct semanage_bool_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_activedb; typedef struct dbase_activedb dbase_t; #define DBASE_DEFINED #include #include #include #include #include "boolean_internal.h" #include "database_activedb.h" #include "parse_utils.h" #include "debug.h" static int bool_read_list(semanage_handle_t * handle, semanage_bool_t *** booleans, unsigned int *count) { semanage_bool_t **tmp_booleans = NULL; unsigned int tmp_count = 0; int i; char **names = NULL; int len = 0; /* Fetch boolean names */ if (security_get_boolean_names(&names, &len) < 0) { ERR(handle, "could not get list of boolean names"); goto err; } /* Allocate a sufficiently large array */ tmp_booleans = malloc(sizeof(semanage_bool_t *) * len); if (tmp_booleans == NULL) goto omem; /* Create records one by one */ for (i = 0; i < len; i++) { int value; if (semanage_bool_create(handle, &tmp_booleans[i]) < 0) goto err; tmp_count++; if (semanage_bool_set_name(handle, tmp_booleans[i], names[i]) < 0) goto err; value = security_get_boolean_active(names[i]); if (value < 0) { ERR(handle, "could not get the value " "for boolean %s", names[i]); goto err; } semanage_bool_set_value(tmp_booleans[i], value); } /* Success */ for (i = 0; i < len; i++) free(names[i]); free(names); *booleans = tmp_booleans; *count = tmp_count; return STATUS_SUCCESS; /* Failure */ omem: ERR(handle, "out of memory"); err: ERR(handle, "could not read boolean list"); for (i = 0; i < len; i++) free(names[i]); free(names); for (i = 0; (unsigned int)i < tmp_count; i++) semanage_bool_free(tmp_booleans[i]); free(tmp_booleans); return STATUS_ERR; } static int bool_commit_list(semanage_handle_t * handle, semanage_bool_t ** booleans, unsigned int count) { SELboolean *blist = NULL; const char *name; unsigned int bcount = 0; unsigned int i; int curvalue, newvalue; /* Allocate a sufficiently large array */ blist = malloc(sizeof(SELboolean) * count); if (blist == NULL) goto omem; /* Populate array */ for (i = 0; i < count; i++) { name = semanage_bool_get_name(booleans[i]); if (!name) goto omem; newvalue = semanage_bool_get_value(booleans[i]); curvalue = security_get_boolean_active(name); if (newvalue == curvalue) continue; blist[bcount].name = strdup(name); if (blist[bcount].name == NULL) goto omem; blist[bcount].value = newvalue; bcount++; } /* Commit */ if (security_set_boolean_list(bcount, blist, 0) < 0) { ERR(handle, "libselinux commit failed"); goto err; } for (i = 0; i < bcount; i++) free(blist[i].name); free(blist); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not commit boolean list"); for (i = 0; i < bcount; i++) free(blist[i].name); free(blist); return STATUS_ERR; } /* BOOL RECORD: ACTIVEDB extension: method table */ record_activedb_table_t SEMANAGE_BOOL_ACTIVEDB_RTABLE = { .read_list = bool_read_list, .commit_list = bool_commit_list, }; int bool_activedb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_activedb_init(handle, &SEMANAGE_BOOL_RTABLE, &SEMANAGE_BOOL_ACTIVEDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_ACTIVEDB_DTABLE; return STATUS_SUCCESS; } void bool_activedb_dbase_release(dbase_config_t * dconfig) { dbase_activedb_release(dconfig->dbase); } libsemanage/src/booleans_file.c0100644 0000000 0000000 00000005633 13756670064 015635 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool record_t; typedef struct semanage_bool_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include #include "boolean_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int bool_print(semanage_handle_t * handle, semanage_bool_t * boolean, FILE * str) { const char *name = semanage_bool_get_name(boolean); int value = semanage_bool_get_value(boolean); if (fprintf(str, "%s=%d\n", name, value) < 0) { ERR(handle, "could not print boolean %s to stream", name); return STATUS_ERR; } return STATUS_SUCCESS; } static int bool_parse(semanage_handle_t * handle, parse_info_t * info, semanage_bool_t * boolean) { int value = 0; char *str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Extract name */ if (parse_fetch_string(handle, info, &str, '=') < 0) goto err; if (semanage_bool_set_name(handle, boolean, str) < 0) goto err; free(str); str = NULL; /* Assert = */ if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_ch(handle, info, '=') < 0) goto err; /* Extract value */ if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_str(info, "true") != STATUS_NODATA) value = 1; else if (parse_optional_str(info, "TRUE") != STATUS_NODATA) value = 1; else if (parse_optional_str(info, "false") != STATUS_NODATA) value = 0; else if (parse_optional_str(info, "FALSE") != STATUS_NODATA) value = 0; else if (parse_fetch_int(handle, info, &value, ' ') < 0) goto err; if (value != 0 && value != 1) { ERR(handle, "invalid boolean value for \"%s\": %u " "(%s: %u)\n%s", semanage_bool_get_name(boolean), value, info->filename, info->lineno, info->orig_line); goto err; } semanage_bool_set_value(boolean, value); if (parse_assert_space(handle, info) < 0) goto err; return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse boolean record"); free(str); parse_dispose_line(info); return STATUS_ERR; } /* BOOL RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_BOOL_FILE_RTABLE = { .parse = bool_parse, .print = bool_print, }; int bool_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_BOOL_RTABLE, &SEMANAGE_BOOL_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void bool_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/booleans_local.c0100644 0000000 0000000 00000003652 13756670064 016007 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool_key record_key_t; typedef struct semanage_bool record_t; #define DBASE_RECORD_DEFINED #include "boolean_internal.h" #include "handle.h" #include "database.h" int semanage_bool_modify_local(semanage_handle_t * handle, const semanage_bool_key_t * key, const semanage_bool_t * data) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_bool_del_local(semanage_handle_t * handle, const semanage_bool_key_t * key) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_bool_query_local(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_bool_exists_local(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_bool_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_bool_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_bool_list_local(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_bool_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/booleans_policy.c0100644 0000000 0000000 00000002650 13756670064 016211 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool_key record_key_t; typedef struct semanage_bool record_t; #define DBASE_RECORD_DEFINED #include "boolean_internal.h" #include "handle.h" #include "database.h" int semanage_bool_query(semanage_handle_t * handle, const semanage_bool_key_t * key, semanage_bool_t ** response) { dbase_config_t *dconfig = semanage_bool_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_bool_exists(semanage_handle_t * handle, const semanage_bool_key_t * key, int *response) { dbase_config_t *dconfig = semanage_bool_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_bool_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_bool_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_bool_iterate(semanage_handle_t * handle, int (*handler) (const semanage_bool_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_bool_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_bool_list(semanage_handle_t * handle, semanage_bool_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_bool_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/booleans_policydb.c0100644 0000000 0000000 00000004575 13756670064 016527 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_bool; struct semanage_bool_key; typedef struct semanage_bool record_t; typedef struct semanage_bool_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "boolean_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* BOOLEAN RECRORD (SEPOL): POLICYDB extension: method table */ record_policydb_table_t SEMANAGE_BOOL_POLICYDB_RTABLE = { .add = NULL, .modify = NULL, /* FIXME: these casts depend on stucts in libsepol matching structs * in libsemanage. This is incredibly fragile - the casting gets * rid of warnings, but is not type safe. */ .set = (record_policydb_table_set_t) sepol_bool_set, .query = (record_policydb_table_query_t) sepol_bool_query, .count = (record_policydb_table_count_t) sepol_bool_count, .exists = (record_policydb_table_exists_t) sepol_bool_exists, .iterate = (record_policydb_table_iterate_t) sepol_bool_iterate, }; int bool_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_BOOL_RTABLE, &SEMANAGE_BOOL_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void bool_policydb_dbase_release(dbase_config_t * dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/conf-parse.y0100644 0000000 0000000 00000040603 13756670064 015113 0ustar000000000 0000000 /* Authors: Jason Tang * James Athey * * Copyright (C) 2004-2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ %{ #include "semanage_conf.h" #include #include #include #include #include #include #include extern int semanage_lex(void); /* defined in conf-scan.c */ extern int semanage_lex_destroy(void); /* defined in conf-scan.c */ int semanage_error(const char *msg); extern FILE *semanage_in; extern char *semanage_text; static int parse_module_store(char *arg); static int parse_store_root_path(char *arg); static int parse_compiler_path(char *arg); static void semanage_conf_external_prog_destroy(external_prog_t *ep); static int new_external_prog(external_prog_t **chain); static semanage_conf_t *current_conf; static external_prog_t *new_external; static int parse_errors; #define PASSIGN(p1,p2) { free(p1); p1 = p2; } %} %name-prefix "semanage_" %union { int d; char *s; } %token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED TARGET_PLATFORM COMPILER_DIR IGNORE_MODULE_CACHE STORE_ROOT %token LOAD_POLICY_START SETFILES_START SEFCONTEXT_COMPILE_START DISABLE_GENHOMEDIRCON HANDLE_UNKNOWN USEPASSWD IGNOREDIRS %token BZIP_BLOCKSIZE BZIP_SMALL REMOVE_HLL %token VERIFY_MOD_START VERIFY_LINKED_START VERIFY_KERNEL_START BLOCK_END %token PROG_PATH PROG_ARGS %token ARG %type verify_start_tok %% config_file: config_line config_file | /* empty */ ; config_line: single_opt | command_block | verify_block ; single_opt: module_store | version | target_platform | store_root | compiler_dir | ignore_module_cache | expand_check | file_mode | save_previous | save_linked | disable_genhomedircon | usepasswd | ignoredirs | handle_unknown | bzip_blocksize | bzip_small | remove_hll ; module_store: MODULE_STORE '=' ARG { if (parse_module_store($3) != 0) { parse_errors++; YYABORT; } free($3); } ; store_root: STORE_ROOT '=' ARG { if (parse_store_root_path($3) != 0) { parse_errors++; YYABORT; } free($3); } ; compiler_dir: COMPILER_DIR '=' ARG { if (parse_compiler_path($3) != 0) { parse_errors++; YYABORT; } free($3); } ; ignore_module_cache: IGNORE_MODULE_CACHE '=' ARG { if (strcasecmp($3, "true") == 0) current_conf->ignore_module_cache = 1; else if (strcasecmp($3, "false") == 0) current_conf->ignore_module_cache = 0; else { yyerror("disable-caching can only be 'true' or 'false'"); } free($3); } ; version: VERSION '=' ARG { current_conf->policyvers = atoi($3); free($3); if (current_conf->policyvers < sepol_policy_kern_vers_min() || current_conf->policyvers > sepol_policy_kern_vers_max()) { parse_errors++; YYABORT; } } ; target_platform: TARGET_PLATFORM '=' ARG { if (strcasecmp($3, "selinux") == 0) current_conf->target_platform = SEPOL_TARGET_SELINUX; else if (strcasecmp($3, "xen") == 0) current_conf->target_platform = SEPOL_TARGET_XEN; else { yyerror("target_platform can only be 'selinux' or 'xen'"); } free($3); } ; expand_check: EXPAND_CHECK '=' ARG { current_conf->expand_check = atoi($3); free($3); } ; file_mode: FILE_MODE '=' ARG { current_conf->file_mode = strtoul($3, NULL, 8); free($3); } ; save_previous: SAVE_PREVIOUS '=' ARG { if (strcasecmp($3, "true") == 0) current_conf->save_previous = 1; else if (strcasecmp($3, "false") == 0) current_conf->save_previous = 0; else { yyerror("save-previous can only be 'true' or 'false'"); } free($3); } ; save_linked: SAVE_LINKED '=' ARG { if (strcasecmp($3, "true") == 0) current_conf->save_linked = 1; else if (strcasecmp($3, "false") == 0) current_conf->save_linked = 0; else { yyerror("save-linked can only be 'true' or 'false'"); } free($3); } ; disable_genhomedircon: DISABLE_GENHOMEDIRCON '=' ARG { if (strcasecmp($3, "false") == 0) { current_conf->disable_genhomedircon = 0; } else if (strcasecmp($3, "true") == 0) { current_conf->disable_genhomedircon = 1; } else { yyerror("disable-genhomedircon can only be 'true' or 'false'"); } free($3); } usepasswd: USEPASSWD '=' ARG { if (strcasecmp($3, "false") == 0) { current_conf->usepasswd = 0; } else if (strcasecmp($3, "true") == 0) { current_conf->usepasswd = 1; } else { yyerror("usepasswd can only be 'true' or 'false'"); } free($3); } ignoredirs: IGNOREDIRS '=' ARG { current_conf->ignoredirs = strdup($3); free($3); } handle_unknown: HANDLE_UNKNOWN '=' ARG { if (strcasecmp($3, "deny") == 0) { current_conf->handle_unknown = SEPOL_DENY_UNKNOWN; } else if (strcasecmp($3, "reject") == 0) { current_conf->handle_unknown = SEPOL_REJECT_UNKNOWN; } else if (strcasecmp($3, "allow") == 0) { current_conf->handle_unknown = SEPOL_ALLOW_UNKNOWN; } else { yyerror("handle-unknown can only be 'deny', 'reject' or 'allow'"); } free($3); } bzip_blocksize: BZIP_BLOCKSIZE '=' ARG { int blocksize = atoi($3); free($3); if (blocksize > 9) yyerror("bzip-blocksize can only be in the range 0-9"); else current_conf->bzip_blocksize = blocksize; } bzip_small: BZIP_SMALL '=' ARG { if (strcasecmp($3, "false") == 0) { current_conf->bzip_small = 0; } else if (strcasecmp($3, "true") == 0) { current_conf->bzip_small = 1; } else { yyerror("bzip-small can only be 'true' or 'false'"); } free($3); } remove_hll: REMOVE_HLL'=' ARG { if (strcasecmp($3, "false") == 0) { current_conf->remove_hll = 0; } else if (strcasecmp($3, "true") == 0) { current_conf->remove_hll = 1; } else { yyerror("remove-hll can only be 'true' or 'false'"); } free($3); } command_block: command_start external_opts BLOCK_END { if (new_external->path == NULL) { parse_errors++; YYABORT; } } ; command_start: LOAD_POLICY_START { semanage_conf_external_prog_destroy(current_conf->load_policy); current_conf->load_policy = NULL; if (new_external_prog(¤t_conf->load_policy) == -1) { parse_errors++; YYABORT; } } | SETFILES_START { semanage_conf_external_prog_destroy(current_conf->setfiles); current_conf->setfiles = NULL; if (new_external_prog(¤t_conf->setfiles) == -1) { parse_errors++; YYABORT; } } | SEFCONTEXT_COMPILE_START { semanage_conf_external_prog_destroy(current_conf->sefcontext_compile); current_conf->sefcontext_compile = NULL; if (new_external_prog(¤t_conf->sefcontext_compile) == -1) { parse_errors++; YYABORT; } } ; verify_block: verify_start external_opts BLOCK_END { if (new_external->path == NULL) { parse_errors++; YYABORT; } } ; verify_start: verify_start_tok { if ($1 == -1) { parse_errors++; YYABORT; } } ; verify_start_tok: VERIFY_MOD_START {$$ = new_external_prog(¤t_conf->mod_prog);} | VERIFY_LINKED_START {$$ = new_external_prog(¤t_conf->linked_prog);} | VERIFY_KERNEL_START {$$ = new_external_prog(¤t_conf->kernel_prog);} ; external_opts: external_opt external_opts | /* empty */ ; external_opt: PROG_PATH '=' ARG { PASSIGN(new_external->path, $3); } | PROG_ARGS '=' ARG { PASSIGN(new_external->args, $3); } ; %% static int semanage_conf_init(semanage_conf_t * conf) { conf->store_type = SEMANAGE_CON_DIRECT; conf->store_path = strdup(basename(selinux_policy_root())); conf->ignoredirs = NULL; conf->store_root_path = strdup("/var/lib/selinux"); conf->compiler_directory_path = strdup("/usr/libexec/selinux/hll"); conf->policyvers = sepol_policy_kern_vers_max(); conf->target_platform = SEPOL_TARGET_SELINUX; conf->expand_check = 1; conf->handle_unknown = -1; conf->usepasswd = 1; conf->file_mode = 0644; conf->bzip_blocksize = 9; conf->bzip_small = 0; conf->ignore_module_cache = 0; conf->remove_hll = 0; conf->save_previous = 0; conf->save_linked = 0; if ((conf->load_policy = calloc(1, sizeof(*(current_conf->load_policy)))) == NULL) { return -1; } if (access("/sbin/load_policy", X_OK) == 0) { conf->load_policy->path = strdup("/sbin/load_policy"); } else { conf->load_policy->path = strdup("/usr/sbin/load_policy"); } if (conf->load_policy->path == NULL) { return -1; } conf->load_policy->args = NULL; if ((conf->setfiles = calloc(1, sizeof(*(current_conf->setfiles)))) == NULL) { return -1; } if (access("/sbin/setfiles", X_OK) == 0) { conf->setfiles->path = strdup("/sbin/setfiles"); } else { conf->setfiles->path = strdup("/usr/sbin/setfiles"); } if ((conf->setfiles->path == NULL) || (conf->setfiles->args = strdup("-q -c $@ $<")) == NULL) { return -1; } if ((conf->sefcontext_compile = calloc(1, sizeof(*(current_conf->sefcontext_compile)))) == NULL) { return -1; } if (access("/sbin/sefcontext_compile", X_OK) == 0) { conf->sefcontext_compile->path = strdup("/sbin/sefcontext_compile"); } else { conf->sefcontext_compile->path = strdup("/usr/sbin/sefcontext_compile"); } if ((conf->sefcontext_compile->path == NULL) || (conf->sefcontext_compile->args = strdup("$@")) == NULL) { return -1; } return 0; } /* Parse a libsemanage configuration file. THIS FUNCTION IS NOT * THREAD-SAFE! Return a newly allocated semanage_conf_t *. If the * configuration file could be read, parse it; otherwise rely upon * default values. If the file could not be parsed correctly or if * out of memory return NULL. */ semanage_conf_t *semanage_conf_parse(const char *config_filename) { if ((current_conf = calloc(1, sizeof(*current_conf))) == NULL) { return NULL; } if (semanage_conf_init(current_conf) == -1) { goto cleanup; } if ((semanage_in = fopen(config_filename, "r")) == NULL) { /* configuration file does not exist or could not be * read. THIS IS NOT AN ERROR. just rely on the * defaults. */ return current_conf; } parse_errors = 0; semanage_parse(); fclose(semanage_in); semanage_lex_destroy(); if (parse_errors != 0) { goto cleanup; } return current_conf; cleanup: semanage_conf_destroy(current_conf); return NULL; } static void semanage_conf_external_prog_destroy(external_prog_t * ep) { while (ep != NULL) { external_prog_t *next = ep->next; free(ep->path); free(ep->args); free(ep); ep = next; } } /* Deallocates all space associated with a configuration struct, * including the pointer itself. */ void semanage_conf_destroy(semanage_conf_t * conf) { if (conf != NULL) { free(conf->store_path); free(conf->ignoredirs); free(conf->store_root_path); free(conf->compiler_directory_path); semanage_conf_external_prog_destroy(conf->load_policy); semanage_conf_external_prog_destroy(conf->setfiles); semanage_conf_external_prog_destroy(conf->sefcontext_compile); semanage_conf_external_prog_destroy(conf->mod_prog); semanage_conf_external_prog_destroy(conf->linked_prog); semanage_conf_external_prog_destroy(conf->kernel_prog); free(conf); } } int semanage_error(const char *msg) { fprintf(stderr, "error parsing semanage configuration file: %s\n", msg); parse_errors++; return 0; } /* Take the string argument for a module store. If it is exactly the * word "direct" then have libsemanage directly manipulate the module * store. The policy path will default to the active policy directory. * Otherwise if it begins with a forward slash interpret it as * an absolute path to a named socket, to which a policy server is * listening on the other end. Otherwise treat it as the host name to * an external server; if there is a colon in the name then everything * after gives a port number. The default port number is 4242. * Returns 0 on success, -1 if out of memory, -2 if a port number is * illegal. */ static int parse_module_store(char *arg) { /* arg is already a strdup()ed copy of yytext */ if (arg == NULL) { return -1; } free(current_conf->store_path); if (strcmp(arg, "direct") == 0) { current_conf->store_type = SEMANAGE_CON_DIRECT; current_conf->store_path = strdup(basename(selinux_policy_root())); current_conf->server_port = -1; } else if (*arg == '/') { current_conf->store_type = SEMANAGE_CON_POLSERV_LOCAL; current_conf->store_path = strdup(arg); current_conf->server_port = -1; } else { char *s; current_conf->store_type = SEMANAGE_CON_POLSERV_REMOTE; if ((s = strchr(arg, ':')) == NULL) { current_conf->store_path = arg; current_conf->server_port = 4242; } else { char *endptr; *s = '\0'; current_conf->store_path = arg; current_conf->server_port = strtol(s + 1, &endptr, 10); if (*(s + 1) == '\0' || *endptr != '\0') { return -2; } } } return 0; } static int parse_store_root_path(char *arg) { if (arg == NULL) { return -1; } free(current_conf->store_root_path); current_conf->store_root_path = strdup(arg); return 0; } static int parse_compiler_path(char *arg) { if (arg == NULL) { return -1; } free(current_conf->compiler_directory_path); current_conf->compiler_directory_path = strdup(arg); return 0; } /* Helper function; called whenever configuration file specifies * another external program. Returns 0 on success, -1 if out of * memory. */ static int new_external_prog(external_prog_t ** chain) { if ((new_external = calloc(1, sizeof(*new_external))) == NULL) { return -1; } /* hook this new external program to the end of the chain */ if (*chain == NULL) { *chain = new_external; } else { external_prog_t *prog = *chain; while (prog->next != NULL) { prog = prog->next; } prog->next = new_external; } return 0; } libsemanage/src/conf-scan.l0100644 0000000 0000000 00000006142 13756670064 014710 0ustar000000000 0000000 /* Authors: Jason Tang * James Athey * * Copyright (C) 2004-2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ %{ #include "conf-parse.h" #include #include static char *my_strdup (char * s); static char *my_qstrdup (char * s); %} %option stack prefix="semanage_" %option noinput nounput noyy_push_state noyy_pop_state noyy_top_state noyywrap %x arg %% #.* /* ignore comments */ module-store return MODULE_STORE; store-root return STORE_ROOT; compiler-directory return COMPILER_DIR; ignore-module-cache return IGNORE_MODULE_CACHE; policy-version return VERSION; target-platform return TARGET_PLATFORM; expand-check return EXPAND_CHECK; file-mode return FILE_MODE; save-previous return SAVE_PREVIOUS; save-linked return SAVE_LINKED; disable-genhomedircon return DISABLE_GENHOMEDIRCON; usepasswd return USEPASSWD; ignoredirs return IGNOREDIRS; handle-unknown return HANDLE_UNKNOWN; bzip-blocksize return BZIP_BLOCKSIZE; bzip-small return BZIP_SMALL; remove-hll return REMOVE_HLL; "[load_policy]" return LOAD_POLICY_START; "[setfiles]" return SETFILES_START; "[sefcontext_compile]" return SEFCONTEXT_COMPILE_START; "[verify module]" return VERIFY_MOD_START; "[verify linked]" return VERIFY_LINKED_START; "[verify kernel]" return VERIFY_KERNEL_START; "[end]" return BLOCK_END; path return PROG_PATH; args return PROG_ARGS; [ \t]*=[ \t]* BEGIN arg; return '='; [ \t\n]+ /* ignore */ . return semanage_text[0]; \"\" BEGIN INITIAL; semanage_lval.s = NULL; return ARG; \".+\" BEGIN INITIAL; semanage_lval.s = my_qstrdup(semanage_text); return ARG; .*[^\"\n] BEGIN INITIAL; semanage_lval.s = my_strdup(semanage_text); return ARG; .|\n BEGIN INITIAL; semanage_lval.s = NULL; return ARG; %% /* Like strdup(), but also trim leading and trailing whitespace. * Returns NULL on error. */ static char *my_strdup(char *s) { char *t; while (isspace(*s)) { s++; } t = s + strlen(s) - 1; while (t >= s && isspace(*t)) { *t = '\0'; t--; } return strdup(s); } /* strdup() a string sans initial and trailing characters. Does /not/ * trim any whitespace. Returns NULL on error. */ static char *my_qstrdup(char *s) { s++; s[strlen(s) - 1] = '\0'; return strdup(s); } libsemanage/src/context_internal.h0100644 0000000 0000000 00000000464 13756670064 016416 0ustar000000000 0000000 #ifndef _SEMANAGE_CONTEXT_INTERNAL_H_ #define _SEMANAGE_CONTEXT_INTERNAL_H_ #include #include "dso.h" hidden_proto(semanage_context_clone) hidden_proto(semanage_context_free) hidden_proto(semanage_context_from_string) hidden_proto(semanage_context_to_string) #endif libsemanage/src/context_record.c0100644 0000000 0000000 00000004556 13756670064 016061 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #include #include "handle.h" typedef sepol_context_t semanage_context_t; #define _SEMANAGE_CONTEXT_DEFINED_ #include "context_internal.h" /* User */ const char *semanage_context_get_user(const semanage_context_t * con) { return sepol_context_get_user(con); } int semanage_context_set_user(semanage_handle_t * handle, semanage_context_t * con, const char *user) { return sepol_context_set_user(handle->sepolh, con, user); } /* Role */ const char *semanage_context_get_role(const semanage_context_t * con) { return sepol_context_get_role(con); } int semanage_context_set_role(semanage_handle_t * handle, semanage_context_t * con, const char *role) { return sepol_context_set_role(handle->sepolh, con, role); } /* Type */ const char *semanage_context_get_type(const semanage_context_t * con) { return sepol_context_get_type(con); } int semanage_context_set_type(semanage_handle_t * handle, semanage_context_t * con, const char *type) { return sepol_context_set_type(handle->sepolh, con, type); } /* MLS */ const char *semanage_context_get_mls(const semanage_context_t * con) { return sepol_context_get_mls(con); } int semanage_context_set_mls(semanage_handle_t * handle, semanage_context_t * con, const char *mls_range) { return sepol_context_set_mls(handle->sepolh, con, mls_range); } /* Create/Clone/Destroy */ int semanage_context_create(semanage_handle_t * handle, semanage_context_t ** con_ptr) { return sepol_context_create(handle->sepolh, con_ptr); } int semanage_context_clone(semanage_handle_t * handle, const semanage_context_t * con, semanage_context_t ** con_ptr) { return sepol_context_clone(handle->sepolh, con, con_ptr); } hidden_def(semanage_context_clone) void semanage_context_free(semanage_context_t * con) { sepol_context_free(con); } hidden_def(semanage_context_free) /* Parse to/from string */ int semanage_context_from_string(semanage_handle_t * handle, const char *str, semanage_context_t ** con) { return sepol_context_from_string(handle->sepolh, str, con); } hidden_def(semanage_context_from_string) int semanage_context_to_string(semanage_handle_t * handle, const semanage_context_t * con, char **str_ptr) { return sepol_context_to_string(handle->sepolh, con, str_ptr); } hidden_def(semanage_context_to_string) libsemanage/src/database.c0100644 0000000 0000000 00000010162 13756670064 014571 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #include #include "semanage_store.h" #include "semanage_conf.h" #include "database.h" #include "debug.h" static int assert_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dconfig->dtable == NULL) { ERR(handle, "A direct or server connection is needed " "to use this function - please call " "the corresponding connect() method"); return STATUS_ERR; } return STATUS_SUCCESS; } static int enter_ro(semanage_handle_t * handle, dbase_config_t * dconfig) { if (assert_init(handle, dconfig) < 0) goto err; if (!handle->is_in_transaction && handle->conf->store_type == SEMANAGE_CON_DIRECT) { if (semanage_get_active_lock(handle) < 0) { ERR(handle, "could not get the active lock"); goto err; } } if (dconfig->dtable->cache(handle, dconfig->dbase) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not enter read-only section"); return STATUS_ERR; } static inline int exit_ro(semanage_handle_t * handle) { int commit_num = handle->funcs->get_serial(handle); if (!handle->is_in_transaction && handle->conf->store_type == SEMANAGE_CON_DIRECT) semanage_release_active_lock(handle); return commit_num; } static int enter_rw(semanage_handle_t * handle, dbase_config_t * dconfig) { if (assert_init(handle, dconfig) < 0) goto err; if (!handle->is_in_transaction) { ERR(handle, "this operation requires a transaction"); goto err; } if (dconfig->dtable->cache(handle, dconfig->dbase) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not enter read-write section"); return STATUS_ERR; } int dbase_modify(semanage_handle_t * handle, dbase_config_t * dconfig, const record_key_t * key, const record_t * data) { if (enter_rw(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->modify(handle, dconfig->dbase, key, data) < 0) return STATUS_ERR; return STATUS_SUCCESS; } int dbase_set(semanage_handle_t * handle, dbase_config_t * dconfig, const record_key_t * key, const record_t * data) { if (enter_rw(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->set(handle, dconfig->dbase, key, data) < 0) return STATUS_ERR; return STATUS_SUCCESS; } int dbase_del(semanage_handle_t * handle, dbase_config_t * dconfig, const record_key_t * key) { if (enter_rw(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->del(handle, dconfig->dbase, key) < 0) return STATUS_ERR; return STATUS_SUCCESS; } int dbase_query(semanage_handle_t * handle, dbase_config_t * dconfig, const record_key_t * key, record_t ** response) { if (enter_ro(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->query(handle, dconfig->dbase, key, response) < 0) { exit_ro(handle); return STATUS_ERR; } return exit_ro(handle); } int dbase_exists(semanage_handle_t * handle, dbase_config_t * dconfig, const record_key_t * key, int *response) { if (enter_ro(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->exists(handle, dconfig->dbase, key, response) < 0) { exit_ro(handle); return STATUS_ERR; } return exit_ro(handle); } int dbase_count(semanage_handle_t * handle, dbase_config_t * dconfig, unsigned int *response) { if (enter_ro(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->count(handle, dconfig->dbase, response) < 0) { exit_ro(handle); return STATUS_ERR; } return exit_ro(handle); } int dbase_iterate(semanage_handle_t * handle, dbase_config_t * dconfig, int (*fn) (const record_t * record, void *fn_arg), void *fn_arg) { if (enter_ro(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->iterate(handle, dconfig->dbase, fn, fn_arg) < 0) { exit_ro(handle); return STATUS_ERR; } return exit_ro(handle); } int dbase_list(semanage_handle_t * handle, dbase_config_t * dconfig, record_t *** records, unsigned int *count) { if (enter_ro(handle, dconfig) < 0) return STATUS_ERR; if (dconfig->dtable->list(handle, dconfig->dbase, records, count) < 0) { exit_ro(handle); return STATUS_ERR; } return exit_ro(handle); } libsemanage/src/database.h0100644 0000000 0000000 00000015337 13756670064 014607 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_H_ #define _SEMANAGE_DATABASE_H_ #ifndef DBASE_RECORD_DEFINED typedef void *record_t; typedef void *record_key_t; #define DBASE_RECORD_DEFINED #endif #ifndef DBASE_DEFINED typedef void *dbase_t; #define DBASE_DEFINED #endif /* Circular dependency */ struct semanage_handle; /* RECORD interface - method table */ typedef struct record_table { /* Create a record */ int (*create) (struct semanage_handle * handle, record_t ** rec); /* Extract key from record */ int (*key_extract) (struct semanage_handle * handle, const record_t * rec, record_key_t ** key); /* Free record key */ void (*key_free) (record_key_t * key); /* Return 0 if the record matches the key, * -1 if the key represents a record that should * be ordered before this record, and 1 if vice-versa */ int (*compare) (const record_t * rec, const record_key_t * key); /* Return 0 if the record matches record2, * -1 if record2 should be ordered before this record, * and 1 if vice-versa */ int (*compare2) (const record_t * rec, const record_t * rec2); /* Same as above, but dereferences the pointer first. * This function is intenteded to be used as a qsort * comparator. */ int (*compare2_qsort) (const record_t ** rec, const record_t ** rec2); /* Deep-copy clone of this record */ int (*clone) (struct semanage_handle * handle, const record_t * rec, record_t ** new_rec); /* Deallocate record resources. Must sucessfully handle NULL. */ void (*free) (record_t * rec); } record_table_t; /* DBASE interface - method table */ typedef struct dbase_table { /* --------------- Database Functionality ----------- */ /* Note: In all the functions below, the key is property * of the caller, and will not be modified by the database. * In add/set/modify, the data is also property of the caller */ /* Add the specified record to * the database. No check for duplicates is performed */ int (*add) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key, const record_t * data); /* Add the specified record to the * database if it not present. * If it's present, replace it */ int (*modify) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key, const record_t * data); /* Modify the specified record in the database * if it is present. Fail if it does not yet exist */ int (*set) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key, const record_t * data); /* Delete a record */ int (*del) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key); /* Clear all records, and leave the database in * cached, modified state. This function does * not require a call to cache() */ int (*clear) (struct semanage_handle * handle, dbase_t * dbase); /* Retrieve a record * * Note: the resultant record * becomes property of the caller, and * must be freed accordingly */ int (*query) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key, record_t ** response); /* Check if a record exists */ int (*exists) (struct semanage_handle * handle, dbase_t * dbase, const record_key_t * key, int *response); /* Count the number of records */ int (*count) (struct semanage_handle * handle, dbase_t * dbase, unsigned int *response); /* Execute the specified handler over * the records of this database. The handler * can signal a successful exit by returning 1, * an error exit by returning -1, and continue by * returning 0 * * Note: The record passed into the iterate handler * may or may not persist after the handler invocation, * and writing to it has unspecified behavior. It *must* * be cloned if modified, or preserved. * * Note: The iterate handler may not invoke any other * semanage read functions outside a transaction. It is only * reentrant while in transaction. The iterate handler may * not modify the underlying database. */ int (*iterate) (struct semanage_handle * handle, dbase_t * dbase, int (*fn) (const record_t * record, void *varg), void *fn_arg); /* Construct a list of all records in this database * * Note: The list returned becomes property of the caller, * and must be freed accordingly. */ int (*list) (struct semanage_handle * handle, dbase_t * dbase, record_t *** records, unsigned int *count); /* ---------- Cache/Transaction Management ---------- */ /* Cache the database (if supported). * This function must be invoked before using * any of the database functions above. It may be invoked * multiple times, and will update the cache if a commit * occurred between invocations */ int (*cache) (struct semanage_handle * handle, dbase_t * dbase); /* Forgets all changes that haven't been written * to the database backend */ void (*drop_cache) (dbase_t * dbase); /* Checks if there are any changes not written to the backend */ int (*is_modified) (dbase_t * dbase); /* Writes the database changes to its backend */ int (*flush) (struct semanage_handle * handle, dbase_t * dbase); /* ------------- Polymorphism ----------------------- */ /* Retrieves the record table for this database, * which specifies how to perform basic operations * on each record. */ record_table_t *(*get_rtable) (dbase_t * dbase); } dbase_table_t; typedef struct dbase_config { /* Database state */ dbase_t *dbase; /* Database methods */ dbase_table_t *dtable; } dbase_config_t; extern int dbase_add(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key, const record_t * data); extern int dbase_modify(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key, const record_t * data); extern int dbase_set(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key, const record_t * data); extern int dbase_del(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key); extern int dbase_query(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key, record_t ** response); extern int dbase_exists(struct semanage_handle *handle, dbase_config_t * dconfig, const record_key_t * key, int *response); extern int dbase_count(struct semanage_handle *handle, dbase_config_t * dconfig, unsigned int *response); extern int dbase_iterate(struct semanage_handle *handle, dbase_config_t * dconfig, int (*fn) (const record_t * record, void *fn_arg), void *fn_arg); extern int dbase_list(struct semanage_handle *handle, dbase_config_t * dconfig, record_t *** records, unsigned int *count); #endif libsemanage/src/database_activedb.c0100644 0000000 0000000 00000007667 13756670064 016452 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: dbase_activedb_t (Active/Kernel) * Extends: dbase_llist_t (Linked List) * Implements: dbase_t (Database) */ struct dbase_activedb; typedef struct dbase_activedb dbase_t; #define DBASE_DEFINED #include #include #include #include "debug.h" #include "handle.h" #include "database_activedb.h" #include "database_llist.h" /* ACTIVEDB dbase */ struct dbase_activedb { /* Parent object - must always be * the first field - here we are using * a linked list to store the records */ dbase_llist_t llist; /* ACTIVEDB extension */ record_activedb_table_t *ratable; }; static int dbase_activedb_cache(semanage_handle_t * handle, dbase_activedb_t * dbase) { record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist); record_activedb_table_t *ratable = dbase->ratable; record_t **records = NULL; unsigned int rcount = 0; unsigned int i = 0; /* Already cached */ if (!dbase_llist_needs_resync(handle, &dbase->llist)) return STATUS_SUCCESS; /* Update cache serial */ dbase_llist_cache_init(&dbase->llist); if (dbase_llist_set_serial(handle, &dbase->llist) < 0) goto err; /* Fetch the entire list */ if (ratable->read_list(handle, &records, &rcount) < 0) goto err; /* Add records one by one */ for (; i < rcount; i++) { if (dbase_llist_cache_prepend(handle, &dbase->llist, records[i]) < 0) goto err; rtable->free(records[i]); } free(records); return STATUS_SUCCESS; err: ERR(handle, "could not cache active database"); for (; i < rcount; i++) rtable->free(records[i]); dbase_llist_drop_cache(&dbase->llist); free(records); return STATUS_ERR; } static int dbase_activedb_flush(semanage_handle_t * handle, dbase_activedb_t * dbase) { record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist); record_activedb_table_t *ratable = dbase->ratable; record_t **records = NULL; unsigned int rcount = 0; unsigned int i; /* Not cached, or not modified - flush is not necessary */ if (!dbase_llist_is_modified(&dbase->llist)) return STATUS_SUCCESS; /* Fetch list */ if (dbase_llist_list(handle, &dbase->llist, &records, &rcount) < 0) goto err; /* Commit */ if (ratable->commit_list(handle, records, rcount) < 0) goto err; for (i = 0; i < rcount; i++) rtable->free(records[i]); free(records); dbase_llist_set_modified(&dbase->llist, 0); return STATUS_SUCCESS; err: for (i = 0; i < rcount; i++) rtable->free(records[i]); free(records); ERR(handle, "could not flush active database"); return STATUS_ERR; } int dbase_activedb_init(semanage_handle_t * handle, record_table_t * rtable, record_activedb_table_t * ratable, dbase_activedb_t ** dbase) { dbase_activedb_t *tmp_dbase = (dbase_activedb_t *) malloc(sizeof(dbase_activedb_t)); if (!tmp_dbase) goto omem; tmp_dbase->ratable = ratable; dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_ACTIVEDB_DTABLE); *dbase = tmp_dbase; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not initialize active database"); free(tmp_dbase); return STATUS_ERR; } /* Release dbase resources */ void dbase_activedb_release(dbase_activedb_t * dbase) { dbase_llist_drop_cache(&dbase->llist); free(dbase); } /* ACTIVEDB dbase - method table implementation */ dbase_table_t SEMANAGE_ACTIVEDB_DTABLE = { /* Cache/Transactions */ .cache = dbase_activedb_cache, .drop_cache = (void *)dbase_llist_drop_cache, .flush = dbase_activedb_flush, .is_modified = (void *)dbase_llist_is_modified, /* Database API */ .iterate = (void *)dbase_llist_iterate, .exists = (void *)dbase_llist_exists, .list = (void *)dbase_llist_list, .add = (void *)dbase_llist_add, .set = (void *)dbase_llist_set, .del = (void *)dbase_llist_del, .clear = (void *)dbase_llist_clear, .modify = (void *)dbase_llist_modify, .query = (void *)dbase_llist_query, .count = (void *)dbase_llist_count, /* Polymorphism */ .get_rtable = (void *)dbase_llist_get_rtable }; libsemanage/src/database_activedb.h0100644 0000000 0000000 00000002014 13756670064 016434 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_ACTIVEDB_INTERNAL_H_ #define _SEMANAGE_DATABASE_ACTIVEDB_INTERNAL_H_ #include "database.h" #include "handle.h" struct dbase_activedb; typedef struct dbase_activedb dbase_activedb_t; /* ACTIVEDB extension to RECORD interface - method table */ typedef struct record_activedb_table { /* Read a list of records */ int (*read_list) (semanage_handle_t * handle, record_t *** records, unsigned int *count); /* Commit a list of records */ int (*commit_list) (semanage_handle_t * handle, record_t ** records, unsigned int count); } record_activedb_table_t; /* ACTIVEDB - initialization */ extern int dbase_activedb_init(semanage_handle_t * handle, record_table_t * rtable, record_activedb_table_t * ratable, dbase_activedb_t ** dbase); /* ACTIVEDB - release */ extern void dbase_activedb_release(dbase_activedb_t * dbase); /* ACTIVEDB - method table implementation */ extern dbase_table_t SEMANAGE_ACTIVEDB_DTABLE; #endif libsemanage/src/database_file.c0100644 0000000 0000000 00000011645 13756670064 015577 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: dbase_file_t (File) * Extends: dbase_llist_t (Linked List) * Implements: dbase_t (Database) */ struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include #include #include "debug.h" #include "handle.h" #include "parse_utils.h" #include "database_file.h" #include "database_llist.h" #include "semanage_store.h" /* FILE dbase */ struct dbase_file { /* Parent object - must always be * the first field - here we are using * a linked list to store the records */ dbase_llist_t llist; /* Backing path for read-only[0] and transaction[1] */ const char *path[2]; /* FILE extension */ record_file_table_t *rftable; }; static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase) { record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist); record_file_table_t *rftable = dbase->rftable; record_t *process_record = NULL; int pstatus = STATUS_SUCCESS; parse_info_t *parse_info = NULL; const char *fname = NULL; /* Already cached */ if (!dbase_llist_needs_resync(handle, &dbase->llist)) return STATUS_SUCCESS; /* Update cache serial */ dbase_llist_cache_init(&dbase->llist); if (dbase_llist_set_serial(handle, &dbase->llist) < 0) goto err; fname = dbase->path[handle->is_in_transaction]; if (parse_init(handle, fname, NULL, &parse_info) < 0) goto err; if (parse_open(handle, parse_info) < 0) goto err; /* Main processing loop */ do { /* Create record */ if (rtable->create(handle, &process_record) < 0) goto err; /* Parse record */ pstatus = rftable->parse(handle, parse_info, process_record); /* Parse error */ if (pstatus < 0) goto err; /* End of file */ else if (pstatus == STATUS_NODATA) break; /* Prepend to cache */ if (dbase_llist_cache_prepend(handle, &dbase->llist, process_record) < 0) goto err; rtable->free(process_record); process_record = NULL; } while (pstatus != STATUS_NODATA); rtable->free(process_record); parse_close(parse_info); parse_release(parse_info); return STATUS_SUCCESS; err: ERR(handle, "could not cache file database"); rtable->free(process_record); if (parse_info) { parse_close(parse_info); parse_release(parse_info); } dbase_llist_drop_cache(&dbase->llist); return STATUS_ERR; } /* Flush database to file */ static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase) { record_file_table_t *rftable = dbase->rftable; cache_entry_t *ptr; const char *fname = NULL; FILE *str = NULL; mode_t mask; if (!dbase_llist_is_modified(&dbase->llist)) return STATUS_SUCCESS; fname = dbase->path[handle->is_in_transaction]; mask = umask(0077); str = fopen(fname, "w"); umask(mask); if (!str) { ERR(handle, "could not open %s for writing: %s", fname, strerror(errno)); goto err; } __fsetlocking(str, FSETLOCKING_BYCALLER); if (fprintf(str, "# This file is auto-generated by libsemanage\n" "# Do not edit directly.\n\n") < 0) { ERR(handle, "could not write file header for %s", fname); goto err; } for (ptr = dbase->llist.cache_tail; ptr != NULL; ptr = ptr->prev) { if (rftable->print(handle, ptr->data, str) < 0) goto err; } dbase_llist_set_modified(&dbase->llist, 0); fclose(str); return STATUS_SUCCESS; err: if (str != NULL) fclose(str); ERR(handle, "could not flush database to file"); return STATUS_ERR; } int dbase_file_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, record_table_t * rtable, record_file_table_t * rftable, dbase_file_t ** dbase) { dbase_file_t *tmp_dbase = (dbase_file_t *) malloc(sizeof(dbase_file_t)); if (!tmp_dbase) goto omem; tmp_dbase->path[0] = path_ro; tmp_dbase->path[1] = path_rw; tmp_dbase->rftable = rftable; dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_FILE_DTABLE); *dbase = tmp_dbase; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not initialize file database"); free(tmp_dbase); return STATUS_ERR; } /* Release dbase resources */ void dbase_file_release(dbase_file_t * dbase) { dbase_llist_drop_cache(&dbase->llist); free(dbase); } /* FILE dbase - method table implementation */ dbase_table_t SEMANAGE_FILE_DTABLE = { /* Cache/Transactions */ .cache = dbase_file_cache, .drop_cache = (void *)dbase_llist_drop_cache, .flush = dbase_file_flush, .is_modified = (void *)dbase_llist_is_modified, /* Database API */ .iterate = (void *)dbase_llist_iterate, .exists = (void *)dbase_llist_exists, .list = (void *)dbase_llist_list, .add = (void *)dbase_llist_add, .set = (void *)dbase_llist_set, .del = (void *)dbase_llist_del, .clear = (void *)dbase_llist_clear, .modify = (void *)dbase_llist_modify, .query = (void *)dbase_llist_query, .count = (void *)dbase_llist_count, /* Polymorphism */ .get_rtable = (void *)dbase_llist_get_rtable }; libsemanage/src/database_file.h0100644 0000000 0000000 00000002227 13756670064 015600 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_FILE_INTERNAL_H_ #define _SEMANAGE_DATABASE_FILE_INTERNAL_H_ #include #include "database.h" #include "parse_utils.h" #include "handle.h" struct dbase_file; typedef struct dbase_file dbase_file_t; /* FILE extension to RECORD interface - method table */ typedef struct record_file_table { /* Fill record structuure based on supplied parse info. * Parser must return STATUS_NODATA when EOF is encountered. * Parser must handle NULL file stream correctly */ int (*parse) (semanage_handle_t * handle, parse_info_t * info, record_t * record); /* Print record to stream */ int (*print) (semanage_handle_t * handle, record_t * record, FILE * str); } record_file_table_t; /* FILE - initialization */ extern int dbase_file_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, record_table_t * rtable, record_file_table_t * rftable, dbase_file_t ** dbase); /* FILE - release */ extern void dbase_file_release(dbase_file_t * dbase); /* FILE - method table implementation */ extern dbase_table_t SEMANAGE_FILE_DTABLE; #endif libsemanage/src/database_join.c0100644 0000000 0000000 00000016470 13756670064 015620 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: dbase_join_t (Join) * Extends: dbase_llist_t (Linked List) * Implements: dbase_t (Database) */ struct dbase_join; typedef struct dbase_join dbase_t; #define DBASE_DEFINED #include #include "user_internal.h" #include "debug.h" #include "handle.h" #include "database_join.h" #include "database_llist.h" /* JOIN dbase */ struct dbase_join { /* Parent object - must always be * the first field - here we are using * a linked list to store the records */ dbase_llist_t llist; /* Backing databases - for each * thing being joined */ dbase_config_t *join1; dbase_config_t *join2; /* JOIN extension */ record_join_table_t *rjtable; }; static int dbase_join_cache(semanage_handle_t * handle, dbase_join_t * dbase) { /* Extract all the object tables information */ dbase_t *dbase1 = dbase->join1->dbase; dbase_t *dbase2 = dbase->join2->dbase; dbase_table_t *dtable1 = dbase->join1->dtable; dbase_table_t *dtable2 = dbase->join2->dtable; record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist); record_join_table_t *rjtable = dbase->rjtable; record_table_t *rtable1 = dtable1->get_rtable(dbase1); record_table_t *rtable2 = dtable2->get_rtable(dbase2); record_key_t *rkey = NULL; record_t *record = NULL; record1_t **records1 = NULL; record2_t **records2 = NULL; unsigned int rcount1 = 0, rcount2 = 0, i = 0, j = 0; /* Already cached */ if (!dbase_llist_needs_resync(handle, &dbase->llist)) return STATUS_SUCCESS; /* Update cache serial */ dbase_llist_cache_init(&dbase->llist); if (dbase_llist_set_serial(handle, &dbase->llist) < 0) goto err; /* First cache any child dbase, which must * be the first thing done when calling dbase * functions internally */ if (dtable1->cache(handle, dbase1) < 0) goto err; if (dtable2->cache(handle, dbase2) < 0) goto err; /* Fetch records */ if (dtable1->list(handle, dbase1, &records1, &rcount1) < 0) goto err; if (dtable2->list(handle, dbase2, &records2, &rcount2) < 0) goto err; /* Sort for quicker merge later */ qsort(records1, rcount1, sizeof(record1_t *), (int (*)(const void *, const void *))rtable1->compare2_qsort); qsort(records2, rcount2, sizeof(record2_t *), (int (*)(const void *, const void *))rtable2->compare2_qsort); /* Now merge into this dbase */ while (i < rcount1 || j < rcount2) { int rc; /* End of one list, or the other */ if (i == rcount1) rc = -1; else if (j == rcount2) rc = 1; /* Still more records to go, compare them */ else { if (rtable1->key_extract(handle, records1[i], &rkey) < 0) goto err; rc = rtable2->compare(records2[j], rkey); rtable->key_free(rkey); rkey = NULL; } /* Missing record1 data */ if (rc < 0) { if (rjtable->join(handle, NULL, records2[j], &record) < 0) goto err; j++; } /* Missing record2 data */ else if (rc > 0) { if (rjtable->join(handle, records1[i], NULL, &record) < 0) goto err; i++; } /* Both records available */ else { if (rjtable->join(handle, records1[i], records2[j], &record) < 0) goto err; i++; j++; } /* Add result record to database */ if (dbase_llist_cache_prepend(handle, &dbase->llist, record) < 0) goto err; rtable->free(record); record = NULL; } /* Update cache serial */ if (dbase_llist_set_serial(handle, &dbase->llist) < 0) goto err; for (i = 0; i < rcount1; i++) rtable1->free(records1[i]); for (i = 0; i < rcount2; i++) rtable2->free(records2[i]); free(records1); free(records2); return STATUS_SUCCESS; err: ERR(handle, "could not cache join database"); for (i = 0; i < rcount1; i++) rtable1->free(records1[i]); for (i = 0; i < rcount2; i++) rtable2->free(records2[i]); free(records1); free(records2); rtable->key_free(rkey); rtable->free(record); dbase_llist_drop_cache(&dbase->llist); return STATUS_ERR; } /* Flush database */ static int dbase_join_flush(semanage_handle_t * handle, dbase_join_t * dbase) { /* Extract all the object tables information */ dbase_t *dbase1 = dbase->join1->dbase; dbase_t *dbase2 = dbase->join2->dbase; dbase_table_t *dtable1 = dbase->join1->dtable; dbase_table_t *dtable2 = dbase->join2->dtable; record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist); record_join_table_t *rjtable = dbase->rjtable; record_table_t *rtable1 = dtable1->get_rtable(dbase1); record_table_t *rtable2 = dtable2->get_rtable(dbase2); cache_entry_t *ptr; record_key_t *rkey = NULL; record1_t *record1 = NULL; record2_t *record2 = NULL; /* No effect of flush */ if (!dbase_llist_is_modified(&dbase->llist)) return STATUS_SUCCESS; /* Then clear all records from the cache. * This is *not* the same as dropping the cache - it's an explicit * request to delete all current records. We need to do * this because we don't store delete deltas for the join, * so we must re-add all records from scratch */ if (dtable1->clear(handle, dbase1) < 0) goto err; if (dtable2->clear(handle, dbase2) < 0) goto err; /* For each record, split, and add parts into their corresponding databases */ for (ptr = dbase->llist.cache_tail; ptr != NULL; ptr = ptr->prev) { if (rtable->key_extract(handle, ptr->data, &rkey) < 0) goto err; if (rjtable->split(handle, ptr->data, &record1, &record2) < 0) goto err; if (dtable1->add(handle, dbase1, rkey, record1) < 0) goto err; if (dtable2->add(handle, dbase2, rkey, record2) < 0) goto err; rtable->key_free(rkey); rtable1->free(record1); rtable2->free(record2); rkey = NULL; record1 = NULL; record2 = NULL; } /* Note that this function does not flush the child databases, it * leaves that decision up to higher-level code */ dbase_llist_set_modified(&dbase->llist, 0); return STATUS_SUCCESS; err: ERR(handle, "could not flush join database"); rtable->key_free(rkey); rtable1->free(record1); rtable2->free(record2); return STATUS_ERR; } int dbase_join_init(semanage_handle_t * handle, record_table_t * rtable, record_join_table_t * rjtable, dbase_config_t * join1, dbase_config_t * join2, dbase_t ** dbase) { dbase_join_t *tmp_dbase = malloc(sizeof(dbase_join_t)); if (!tmp_dbase) goto omem; dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_JOIN_DTABLE); tmp_dbase->rjtable = rjtable; tmp_dbase->join1 = join1; tmp_dbase->join2 = join2; *dbase = tmp_dbase; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not initialize join database"); free(tmp_dbase); return STATUS_ERR; } /* Release dbase resources */ void dbase_join_release(dbase_join_t * dbase) { dbase_llist_drop_cache(&dbase->llist); free(dbase); } /* JOIN dbase - method table implementation */ dbase_table_t SEMANAGE_JOIN_DTABLE = { /* Cache/Transactions */ .cache = dbase_join_cache, .drop_cache = (void *)dbase_llist_drop_cache, .flush = dbase_join_flush, .is_modified = (void *)dbase_llist_is_modified, /* Database API */ .iterate = (void *)dbase_llist_iterate, .exists = (void *)dbase_llist_exists, .list = (void *)dbase_llist_list, .add = (void *)dbase_llist_add, .set = (void *)dbase_llist_set, .del = (void *)dbase_llist_del, .clear = (void *)dbase_llist_clear, .modify = (void *)dbase_llist_modify, .query = (void *)dbase_llist_query, .count = (void *)dbase_llist_count, /* Polymorphism */ .get_rtable = (void *)dbase_llist_get_rtable }; libsemanage/src/database_join.h0100644 0000000 0000000 00000002342 13756670064 015616 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_JOIN_INTERNAL_H_ #define _SEMANAGE_DATABASE_JOIN_INTERNAL_H_ #include "database.h" #include "handle.h" #ifndef DBASE_RECORD_JOIN_DEFINED typedef void *record1_t; typedef void *record2_t; #define DBASE_RECORD_JOIN_DEFINED #endif struct dbase_join; typedef struct dbase_join dbase_join_t; /* JOIN extension to RECORD interface - method table */ typedef struct record_join_table { /* Join two records together. * One of the provided records could be NULL */ int (*join) (semanage_handle_t * handle, const record1_t * record1, const record2_t * record2, record_t ** result); /* Splits a record into two */ int (*split) (semanage_handle_t * handle, const record_t * record, record1_t ** split1, record2_t ** split2); } record_join_table_t; /* JOIN - initialization */ extern int dbase_join_init(semanage_handle_t * handle, record_table_t * rtable, record_join_table_t * rjtable, dbase_config_t * join1, dbase_config_t * join2, dbase_join_t ** dbase); /* FILE - release */ extern void dbase_join_release(dbase_join_t * dbase); /* JOIN - method table implementation */ extern dbase_table_t SEMANAGE_JOIN_DTABLE; #endif libsemanage/src/database_llist.c0100644 0000000 0000000 00000017155 13756670064 016011 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: dbase_llist_t (Linked List) * Partially Implements: dbase_t (Database) */ struct dbase_llist; typedef struct dbase_llist dbase_t; #define DBASE_DEFINED #include #include "debug.h" #include "handle.h" #include "database_llist.h" int dbase_llist_needs_resync(semanage_handle_t * handle, dbase_llist_t * dbase) { int cache_serial; if (dbase->cache_serial < 0) return 1; cache_serial = handle->funcs->get_serial(handle); if (cache_serial < 0) return 1; if (cache_serial != dbase->cache_serial) { dbase_llist_drop_cache(dbase); dbase->cache_serial = -1; return 1; } return 0; } /* Helper for adding records to the cache */ int dbase_llist_cache_prepend(semanage_handle_t * handle, dbase_llist_t * dbase, const record_t * data) { /* Initialize */ cache_entry_t *entry = (cache_entry_t *) malloc(sizeof(cache_entry_t)); if (entry == NULL) goto omem; if (dbase->rtable->clone(handle, data, &entry->data) < 0) goto err; entry->prev = NULL; entry->next = dbase->cache; /* Link */ if (dbase->cache != NULL) dbase->cache->prev = entry; if (dbase->cache_tail == NULL) dbase->cache_tail = entry; dbase->cache = entry; dbase->cache_sz++; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not cache record"); free(entry); return STATUS_ERR; } void dbase_llist_drop_cache(dbase_llist_t * dbase) { if (dbase->cache_serial < 0) return; cache_entry_t *prev, *ptr = dbase->cache; while (ptr != NULL) { prev = ptr; ptr = ptr->next; dbase->rtable->free(prev->data); free(prev); } dbase->cache_serial = -1; dbase->modified = 0; } int dbase_llist_set_serial(semanage_handle_t * handle, dbase_llist_t * dbase) { int cache_serial = handle->funcs->get_serial(handle); if (cache_serial < 0) { ERR(handle, "could not update cache serial"); return STATUS_ERR; } dbase->cache_serial = cache_serial; return STATUS_SUCCESS; } /* Helper for finding records in the cache */ static int dbase_llist_cache_locate(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, cache_entry_t ** entry) { cache_entry_t *ptr; /* Implemented in parent */ if (dbase->dtable->cache(handle, dbase) < 0) goto err; for (ptr = dbase->cache; ptr != NULL; ptr = ptr->next) { if (!dbase->rtable->compare(ptr->data, key)) { *entry = ptr; return STATUS_SUCCESS; } } return STATUS_NODATA; err: ERR(handle, "could not complete cache lookup"); return STATUS_ERR; } int dbase_llist_exists(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, int *response) { cache_entry_t *entry; int status; status = dbase_llist_cache_locate(handle, dbase, key, &entry); if (status < 0) goto err; *response = (status != STATUS_NODATA); return STATUS_SUCCESS; err: ERR(handle, "could not check if record exists"); return STATUS_ERR; } int dbase_llist_add(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key __attribute__ ((unused)), const record_t * data) { if (dbase_llist_cache_prepend(handle, dbase, data) < 0) goto err; dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not add record to the database"); return STATUS_ERR; } int dbase_llist_set(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, const record_t * data) { cache_entry_t *entry; int status; status = dbase_llist_cache_locate(handle, dbase, key, &entry); if (status < 0) goto err; if (status == STATUS_NODATA) { ERR(handle, "record not found in the database"); goto err; } else { dbase->rtable->free(entry->data); if (dbase->rtable->clone(handle, data, &entry->data) < 0) goto err; } dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not set record value"); return STATUS_ERR; } int dbase_llist_modify(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, const record_t * data) { cache_entry_t *entry; int status; status = dbase_llist_cache_locate(handle, dbase, key, &entry); if (status < 0) goto err; if (status == STATUS_NODATA) { if (dbase_llist_cache_prepend(handle, dbase, data) < 0) goto err; } else { dbase->rtable->free(entry->data); if (dbase->rtable->clone(handle, data, &entry->data) < 0) goto err; } dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not modify record value"); return STATUS_ERR; } hidden int dbase_llist_count(semanage_handle_t * handle __attribute__ ((unused)), dbase_llist_t * dbase, unsigned int *response) { *response = dbase->cache_sz; return STATUS_SUCCESS; } int dbase_llist_query(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, record_t ** response) { cache_entry_t *entry; int status; status = dbase_llist_cache_locate(handle, dbase, key, &entry); if (status < 0 || status == STATUS_NODATA) goto err; if (dbase->rtable->clone(handle, entry->data, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not query record value"); return STATUS_ERR; } int dbase_llist_iterate(semanage_handle_t * handle, dbase_llist_t * dbase, int (*fn) (const record_t * record, void *fn_arg), void *arg) { int rc; cache_entry_t *ptr; for (ptr = dbase->cache_tail; ptr != NULL; ptr = ptr->prev) { rc = fn(ptr->data, arg); if (rc < 0) goto err; else if (rc > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over records"); return STATUS_ERR; } int dbase_llist_del(semanage_handle_t * handle __attribute__ ((unused)), dbase_llist_t * dbase, const record_key_t * key) { cache_entry_t *ptr, *prev = NULL; for (ptr = dbase->cache; ptr != NULL; ptr = ptr->next) { if (!dbase->rtable->compare(ptr->data, key)) { if (prev != NULL) prev->next = ptr->next; else dbase->cache = ptr->next; if (ptr->next != NULL) ptr->next->prev = ptr->prev; else dbase->cache_tail = ptr->prev; dbase->rtable->free(ptr->data); dbase->cache_sz--; free(ptr); dbase->modified = 1; return STATUS_SUCCESS; } else prev = ptr; } return STATUS_SUCCESS; } int dbase_llist_clear(semanage_handle_t * handle, dbase_llist_t * dbase) { int old_serial = dbase->cache_serial; if (dbase_llist_set_serial(handle, dbase) < 0) { ERR(handle, "could not set serial of cleared dbase"); return STATUS_ERR; } if (old_serial >= 0) { cache_entry_t *prev, *ptr = dbase->cache; while (ptr != NULL) { prev = ptr; ptr = ptr->next; dbase->rtable->free(prev->data); free(prev); } } dbase->cache = NULL; dbase->cache_tail = NULL; dbase->cache_sz = 0; dbase->modified = 1; return STATUS_SUCCESS; } int dbase_llist_list(semanage_handle_t * handle, dbase_llist_t * dbase, record_t *** records, unsigned int *count) { cache_entry_t *ptr; record_t **tmp_records = NULL; unsigned int tmp_count; int i = 0; tmp_count = dbase->cache_sz; if (tmp_count > 0) { tmp_records = (record_t **) calloc(tmp_count, sizeof(record_t *)); if (tmp_records == NULL) goto omem; for (ptr = dbase->cache_tail; ptr != NULL; ptr = ptr->prev) { if (dbase->rtable->clone(handle, ptr->data, &tmp_records[i]) < 0) goto err; i++; } } *records = tmp_records; *count = tmp_count; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_records) { for (; i >= 0; i--) dbase->rtable->free(tmp_records[i]); free(tmp_records); } ERR(handle, "could not allocate record array"); return STATUS_ERR; } libsemanage/src/database_llist.h0100644 0000000 0000000 00000006200 13756670064 016003 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_LLIST_INTERNAL_H_ #define _SEMANAGE_DATABASE_LLIST_INTERNAL_H_ #include "database.h" #include "handle.h" /* Representation of the database once loaded in memory */ typedef struct cache_entry { record_t *data; struct cache_entry *prev; struct cache_entry *next; } cache_entry_t; /* LLIST dbase */ typedef struct dbase_llist { /* Method tables */ record_table_t *rtable; dbase_table_t *dtable; /* In-memory representation (cache) */ cache_entry_t *cache; cache_entry_t *cache_tail; unsigned int cache_sz; int cache_serial; int modified; } dbase_llist_t; /* Helpers for internal use only */ static inline void dbase_llist_cache_init(dbase_llist_t * dbase) { dbase->cache = NULL; dbase->cache_tail = NULL; dbase->cache_sz = 0; dbase->cache_serial = -1; dbase->modified = 0; } static inline void dbase_llist_init(dbase_llist_t * dbase, record_table_t * rtable, dbase_table_t * dtable) { dbase->rtable = rtable; dbase->dtable = dtable; dbase_llist_cache_init(dbase); } extern int dbase_llist_cache_prepend(semanage_handle_t * handle, dbase_llist_t * dbase, const record_t * data); extern int dbase_llist_needs_resync(semanage_handle_t * handle, dbase_llist_t * dbase); extern int dbase_llist_set_serial(semanage_handle_t * handle, dbase_llist_t * dbase); static inline void dbase_llist_set_modified(dbase_llist_t * dbase, int status) { dbase->modified = status; } /* LLIST - cache/transactions */ extern void dbase_llist_drop_cache(dbase_llist_t * dbase); static inline int dbase_llist_is_modified(dbase_llist_t * dbase) { return dbase->modified; } /* LLIST - polymorphism */ static inline record_table_t *dbase_llist_get_rtable(dbase_llist_t * dbase) { return dbase->rtable; } /* LLIST - dbase API */ extern int dbase_llist_exists(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, int *response); extern int dbase_llist_add(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, const record_t * data); extern int dbase_llist_set(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, const record_t * data); extern int dbase_llist_modify(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, const record_t * data); extern int dbase_llist_count(semanage_handle_t * handle, dbase_llist_t * dbase, unsigned int *response); extern int dbase_llist_query(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key, record_t ** response); extern int dbase_llist_iterate(semanage_handle_t * handle, dbase_llist_t * dbase, int (*fn) (const record_t * record, void *fn_arg), void *arg); extern int dbase_llist_del(semanage_handle_t * handle, dbase_llist_t * dbase, const record_key_t * key); extern int dbase_llist_clear(semanage_handle_t * handle, dbase_llist_t * dbase); extern int dbase_llist_list(semanage_handle_t * handle, dbase_llist_t * dbase, record_t *** records, unsigned int *count); #endif libsemanage/src/database_policydb.c0100644 0000000 0000000 00000023671 13756670064 016467 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: dbase_policydb_t (Policy) * Implements: dbase_t (Database) */ struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include #include #include #include #include #include "database_policydb.h" #include "semanage_store.h" #include "handle.h" #include "debug.h" /* POLICYDB dbase */ struct dbase_policydb { /* Backing path for read-only[0] and transaction[1] */ const char *path[2]; /* Base record table */ record_table_t *rtable; /* Policy extensions */ record_policydb_table_t *rptable; sepol_policydb_t *policydb; int cache_serial; int modified; int attached; }; static void dbase_policydb_drop_cache(dbase_policydb_t * dbase) { if (dbase->cache_serial >= 0) { sepol_policydb_free(dbase->policydb); dbase->cache_serial = -1; dbase->modified = 0; } } static int dbase_policydb_set_serial(semanage_handle_t * handle, dbase_policydb_t * dbase) { int cache_serial = handle->funcs->get_serial(handle); if (cache_serial < 0) { ERR(handle, "could not update cache serial"); return STATUS_ERR; } dbase->cache_serial = cache_serial; return STATUS_SUCCESS; } static int dbase_policydb_needs_resync(semanage_handle_t * handle, dbase_policydb_t * dbase) { int cache_serial; if (dbase->cache_serial < 0) return 1; cache_serial = handle->funcs->get_serial(handle); if (cache_serial < 0) return 1; if (cache_serial != dbase->cache_serial) { dbase_policydb_drop_cache(dbase); dbase->cache_serial = -1; return 1; } return 0; } static int dbase_policydb_cache(semanage_handle_t * handle, dbase_policydb_t * dbase) { FILE *fp = NULL; sepol_policydb_t *policydb = NULL; sepol_policy_file_t *pf = NULL; const char *fname = NULL; /* Check if cache is needed */ if (dbase->attached) return STATUS_SUCCESS; if (!dbase_policydb_needs_resync(handle, dbase)) return STATUS_SUCCESS; fname = dbase->path[handle->is_in_transaction]; if (sepol_policydb_create(&policydb) < 0) { ERR(handle, "could not create policydb object"); goto err; } /* Try opening file * ENOENT is not fatal - we just create an empty policydb */ fp = fopen(fname, "rb"); if (fp == NULL && errno != ENOENT) { ERR(handle, "could not open %s for reading: %s", fname, strerror(errno)); goto err; } /* If the file was opened successfully, read a policydb */ if (fp != NULL) { __fsetlocking(fp, FSETLOCKING_BYCALLER); if (sepol_policy_file_create(&pf) < 0) { ERR(handle, "could not create policy file object"); goto err; } sepol_policy_file_set_fp(pf, fp); sepol_policy_file_set_handle(pf, handle->sepolh); if (sepol_policydb_read(policydb, pf) < 0) goto err; sepol_policy_file_free(pf); fclose(fp); fp = NULL; } /* Update cache serial */ if (dbase_policydb_set_serial(handle, dbase) < 0) goto err; /* Update the database policydb */ dbase->policydb = policydb; return STATUS_SUCCESS; err: ERR(handle, "could not cache policy database"); if (fp) fclose(fp); sepol_policydb_free(policydb); sepol_policy_file_free(pf); return STATUS_ERR; } static int dbase_policydb_flush(semanage_handle_t * handle __attribute__ ((unused)), dbase_policydb_t * dbase) { if (!dbase->modified) return STATUS_SUCCESS; dbase->modified = 0; /* Stub */ return STATUS_ERR; } /* Check if modified */ static int dbase_policydb_is_modified(dbase_policydb_t * dbase) { return dbase->modified; } int dbase_policydb_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, record_table_t * rtable, record_policydb_table_t * rptable, dbase_policydb_t ** dbase) { dbase_policydb_t *tmp_dbase = (dbase_policydb_t *) malloc(sizeof(dbase_policydb_t)); if (!tmp_dbase) goto omem; tmp_dbase->path[0] = path_ro; tmp_dbase->path[1] = path_rw; tmp_dbase->rtable = rtable; tmp_dbase->rptable = rptable; tmp_dbase->policydb = NULL; tmp_dbase->cache_serial = -1; tmp_dbase->modified = 0; tmp_dbase->attached = 0; *dbase = tmp_dbase; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not initialize policy database"); free(tmp_dbase); return STATUS_ERR; } /* Release dbase resources */ void dbase_policydb_release(dbase_policydb_t * dbase) { dbase_policydb_drop_cache(dbase); free(dbase); } /* Attach to a shared policydb. * This implies drop_cache(), * and prevents flush() and drop_cache() * until detached. */ void dbase_policydb_attach(dbase_policydb_t * dbase, sepol_policydb_t * policydb) { dbase->attached = 1; dbase_policydb_drop_cache(dbase); dbase->policydb = policydb; } /* Detach from a shared policdb. * This implies drop_cache. */ void dbase_policydb_detach(dbase_policydb_t * dbase) { dbase->attached = 0; dbase->modified = 0; } static int dbase_policydb_add(semanage_handle_t * handle, dbase_policydb_t * dbase, const record_key_t * key, const record_t * data) { if (dbase->rptable->add(handle->sepolh, dbase->policydb, key, data) < 0) goto err; dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not add record to the database"); return STATUS_ERR; } static int dbase_policydb_set(semanage_handle_t * handle, dbase_policydb_t * dbase, const record_key_t * key, const record_t * data) { if (dbase->rptable->set(handle->sepolh, dbase->policydb, key, data) < 0) goto err; dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not set record value"); return STATUS_ERR; } static int dbase_policydb_modify(semanage_handle_t * handle, dbase_policydb_t * dbase, const record_key_t * key, const record_t * data) { if (dbase->rptable->modify(handle->sepolh, dbase->policydb, key, data) < 0) goto err; dbase->modified = 1; return STATUS_SUCCESS; err: ERR(handle, "could not modify record value"); return STATUS_ERR; } static int dbase_policydb_del(semanage_handle_t * handle __attribute__ ((unused)), dbase_policydb_t * dbase __attribute__ ((unused)), const record_key_t * key __attribute__ ((unused))) { /* Stub */ return STATUS_ERR; } static int dbase_policydb_clear(semanage_handle_t * handle __attribute__ ((unused)), dbase_policydb_t * dbase __attribute__ ((unused))) { /* Stub */ return STATUS_ERR; } static int dbase_policydb_query(semanage_handle_t * handle, dbase_policydb_t * dbase, const record_key_t * key, record_t ** response) { if (dbase->rptable->query(handle->sepolh, dbase->policydb, key, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not query record value"); return STATUS_ERR; } static int dbase_policydb_exists(semanage_handle_t * handle, dbase_policydb_t * dbase, const record_key_t * key, int *response) { if (dbase->rptable->exists(handle->sepolh, dbase->policydb, key, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not check if record exists"); return STATUS_ERR; } static int dbase_policydb_count(semanage_handle_t * handle, dbase_policydb_t * dbase, unsigned int *response) { if (dbase->rptable->count(handle->sepolh, dbase->policydb, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not count the database records"); return STATUS_ERR; } static int dbase_policydb_iterate(semanage_handle_t * handle, dbase_policydb_t * dbase, int (*fn) (const record_t * record, void *fn_arg), void *arg) { if (dbase->rptable->iterate(handle->sepolh, dbase->policydb, fn, arg) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not iterate over records"); return STATUS_ERR; } struct list_handler_arg { semanage_handle_t *handle; record_table_t *rtable; record_t **records; int pos; }; static int list_handler(const record_t * record, void *varg) { struct list_handler_arg *arg = (struct list_handler_arg *)varg; if (arg->rtable->clone(arg->handle, record, &arg->records[arg->pos]) < 0) return -1; arg->pos++; return 0; } static int dbase_policydb_list(semanage_handle_t * handle, dbase_t * dbase, record_t *** records, unsigned int *count) { record_t **tmp_records = NULL; unsigned int tmp_count; struct list_handler_arg list_arg; list_arg.pos = 0; list_arg.rtable = dbase->rtable; list_arg.handle = handle; if (dbase->rptable->count(handle->sepolh, dbase->policydb, &tmp_count) < 0) goto err; if (tmp_count > 0) { tmp_records = (record_t **) calloc(tmp_count, sizeof(record_t *)); if (tmp_records == NULL) goto omem; list_arg.records = tmp_records; if (dbase->rptable->iterate(handle->sepolh, dbase->policydb, list_handler, &list_arg) < 0) { ERR(handle, "list handler could not extract record"); goto err; } } *records = tmp_records; *count = tmp_count; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_records) { for (; list_arg.pos >= 0; list_arg.pos--) dbase->rtable->free(tmp_records[list_arg.pos]); free(tmp_records); } ERR(handle, "could not list records"); return STATUS_ERR; } static record_table_t *dbase_policydb_get_rtable(dbase_policydb_t * dbase) { return dbase->rtable; } /* POLICYDB dbase - method table implementation */ dbase_table_t SEMANAGE_POLICYDB_DTABLE = { /* Cache/Transactions */ .cache = dbase_policydb_cache, .drop_cache = dbase_policydb_drop_cache, .flush = dbase_policydb_flush, .is_modified = dbase_policydb_is_modified, /* Database Functionality */ .iterate = dbase_policydb_iterate, .exists = dbase_policydb_exists, .list = dbase_policydb_list, .add = dbase_policydb_add, .set = dbase_policydb_set, .del = dbase_policydb_del, .clear = dbase_policydb_clear, .modify = dbase_policydb_modify, .query = dbase_policydb_query, .count = dbase_policydb_count, /* Polymorphism */ .get_rtable = dbase_policydb_get_rtable }; libsemanage/src/database_policydb.h0100644 0000000 0000000 00000007313 13756670064 016467 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_DATABASE_POLICYDB_INTERNAL_H_ #define _SEMANAGE_DATABASE_POLICYDB_INTERNAL_H_ #include #include #include "database.h" #include "handle.h" struct dbase_policydb; typedef struct dbase_policydb dbase_policydb_t; typedef int (*record_policydb_table_add_t) (sepol_handle_t * h, sepol_policydb_t * p, const record_key_t * rkey, const record_t * record); typedef int (*record_policydb_table_modify_t) (sepol_handle_t * h, sepol_policydb_t * p, const record_key_t * rkey, const record_t * record); typedef int (*record_policydb_table_set_t) (sepol_handle_t * h, sepol_policydb_t * p, const record_key_t * rkey, const record_t * record); typedef int (*record_policydb_table_query_t) (sepol_handle_t * h, const sepol_policydb_t * p, const record_key_t * rkey, record_t ** response); typedef int (*record_policydb_table_count_t) (sepol_handle_t * h, const sepol_policydb_t * p, unsigned int *response); typedef int (*record_policydb_table_exists_t) (sepol_handle_t * h, const sepol_policydb_t * p, const record_key_t * rkey, int *response); typedef int (*record_policydb_table_iterate_t) (sepol_handle_t * h, const sepol_policydb_t * p, int (*fn) (const record_t * r, void *fn_arg), void *arg); /* POLICYDB extension to RECORD interface - method table */ typedef struct record_policydb_table { /* Add policy record */ record_policydb_table_add_t add; /* Modify policy record, or add if * the key isn't found */ record_policydb_table_modify_t modify; /* Set policy record */ record_policydb_table_set_t set; /* Query policy record - return the record * or NULL if it isn't found */ record_policydb_table_query_t query; /* Count records */ record_policydb_table_count_t count; /* Check if a record exists */ record_policydb_table_exists_t exists; /* Iterate over records */ record_policydb_table_iterate_t iterate; } record_policydb_table_t; /* Initialize database */ extern int dbase_policydb_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, record_table_t * rtable, record_policydb_table_t * rptable, dbase_policydb_t ** dbase); /* Attach to a shared policydb. * This implies drop_cache(). * and prevents flush() and drop_cache() * until detached. */ extern void dbase_policydb_attach(dbase_policydb_t * dbase, sepol_policydb_t * policydb); /* Detach from a shared policdb. * This implies drop_cache. */ extern void dbase_policydb_detach(dbase_policydb_t * dbase); /* Release allocated resources */ extern void dbase_policydb_release(dbase_policydb_t * dbase); /* POLICYDB database - method table implementation */ extern dbase_table_t SEMANAGE_POLICYDB_DTABLE; #endif libsemanage/src/debug.c0100644 0000000 0000000 00000006261 13756670064 014120 0ustar000000000 0000000 /* Author: Joshua Brindle * Ivan Gyurdiev * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "handle.h" #include "debug.h" int semanage_msg_get_level(semanage_handle_t * handle) { return handle->msg_level; } hidden_def(semanage_msg_get_level) const char *semanage_msg_get_channel(semanage_handle_t * handle) { return handle->msg_channel; } hidden_def(semanage_msg_get_channel) const char *semanage_msg_get_fname(semanage_handle_t * handle) { return handle->msg_fname; } hidden_def(semanage_msg_get_fname) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void hidden semanage_msg_default_handler(void *varg __attribute__ ((unused)), semanage_handle_t * handle, const char *fmt, ...) { FILE *stream = NULL; int errsv = 0; switch (semanage_msg_get_level(handle)) { case SEMANAGE_MSG_ERR: stream = stderr; errsv = errno; break; case SEMANAGE_MSG_WARN: stream = stderr; break; default: stream = stdout; break; } fprintf(stream, "%s.%s: ", semanage_msg_get_channel(handle), semanage_msg_get_fname(handle)); va_list ap; va_start(ap, fmt); vfprintf(stream, fmt, ap); va_end(ap); if (errsv && errsv != ENOMEM) fprintf(stream, " (%s).", strerror(errsv)); fprintf(stream, "\n"); } #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void hidden semanage_msg_relay_handler(void *varg, sepol_handle_t * sepolh, const char *fmt, ...) { va_list ap; semanage_handle_t *sh = varg; char buffer[1024]; if (!sh->msg_callback) return; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); sh->msg_fname = sepol_msg_get_fname(sepolh); sh->msg_channel = sepol_msg_get_channel(sepolh); sh->msg_level = sepol_msg_get_level(sepolh); /* XXX should map values */ sh->msg_callback(sh->msg_callback_arg, sh, "%s", buffer); return; } extern void semanage_msg_set_callback(semanage_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, semanage_handle_t * handle, const char *fmt, ...), void *msg_callback_arg) { handle->msg_callback = msg_callback; handle->msg_callback_arg = msg_callback_arg; } libsemanage/src/debug.h0100644 0000000 0000000 00000005361 13756670064 014125 0ustar000000000 0000000 /* Author: Joshua Brindle * Jason Tang * Ivan Gyurdiev * * Copyright (C) 2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_INTERNAL_DEBUG_H_ #define _SEMANAGE_INTERNAL_DEBUG_H_ #include #include #include #include "handle.h" #include "dso.h" #define STATUS_SUCCESS 0 #define STATUS_ERR -1 #define STATUS_NODATA 1 #define msg_write(handle_arg, level_arg, \ channel_arg, func_arg, ...) do { \ \ if ((handle_arg)->msg_callback) { \ (handle_arg)->msg_fname = func_arg; \ (handle_arg)->msg_channel = channel_arg; \ (handle_arg)->msg_level = level_arg; \ \ (handle_arg)->msg_callback( \ (handle_arg)->msg_callback_arg, \ handle_arg, __VA_ARGS__); \ } \ } while(0) #define ERR(handle, ...) \ msg_write(handle, SEMANAGE_MSG_ERR, "libsemanage", \ __FUNCTION__, __VA_ARGS__) #define INFO(handle, ...) \ msg_write(handle, SEMANAGE_MSG_INFO, "libsemanage", \ __FUNCTION__, __VA_ARGS__) #define WARN(handle, ...) \ msg_write(handle, SEMANAGE_MSG_WARN, "libsemanage", \ __FUNCTION__, __VA_ARGS__) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif extern void hidden semanage_msg_default_handler(void *varg, semanage_handle_t * handle, const char *fmt, ...); #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif extern void hidden semanage_msg_relay_handler(void *varg, sepol_handle_t * handle, const char *fmt, ...); hidden_proto(semanage_msg_get_channel) hidden_proto(semanage_msg_get_fname) hidden_proto(semanage_msg_get_level) #endif libsemanage/src/direct_api.c0100644 0000000 0000000 00000221475 13756670064 015143 0ustar000000000 0000000 /* Author: Jason Tang * Christopher Ashworth * * Copyright (C) 2004-2006 Tresys Technology, LLC * Copyright (C) 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "user_internal.h" #include "seuser_internal.h" #include "port_internal.h" #include "ibpkey_internal.h" #include "ibendport_internal.h" #include "iface_internal.h" #include "boolean_internal.h" #include "fcontext_internal.h" #include "node_internal.h" #include "genhomedircon.h" #include "debug.h" #include "handle.h" #include "modules.h" #include "direct_api.h" #include "semanage_store.h" #include "database_policydb.h" #include "policy.h" #include #include #define PIPE_READ 0 #define PIPE_WRITE 1 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static void semanage_direct_destroy(semanage_handle_t * sh); static int semanage_direct_disconnect(semanage_handle_t * sh); static int semanage_direct_begintrans(semanage_handle_t * sh); static int semanage_direct_commit(semanage_handle_t * sh); static int semanage_direct_install(semanage_handle_t * sh, char *data, size_t data_len, const char *module_name, const char *lang_ext); static int semanage_direct_install_file(semanage_handle_t * sh, const char *module_name); static int semanage_direct_extract(semanage_handle_t * sh, semanage_module_key_t *modkey, int extract_cil, void **mapped_data, size_t *data_len, semanage_module_info_t **modinfo); static int semanage_direct_remove(semanage_handle_t * sh, char *module_name); static int semanage_direct_list(semanage_handle_t * sh, semanage_module_info_t ** modinfo, int *num_modules); static int semanage_direct_get_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int *enabled); static int semanage_direct_set_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int enabled); static int semanage_direct_get_module_info(semanage_handle_t *sh, const semanage_module_key_t *modkey, semanage_module_info_t **modinfo); static int semanage_direct_list_all(semanage_handle_t *sh, semanage_module_info_t **modinfo, int *num_modules); static int semanage_direct_install_info(semanage_handle_t *sh, const semanage_module_info_t *modinfo, char *data, size_t data_len); static int semanage_direct_remove_key(semanage_handle_t *sh, const semanage_module_key_t *modkey); static struct semanage_policy_table direct_funcs = { .get_serial = semanage_direct_get_serial, .destroy = semanage_direct_destroy, .disconnect = semanage_direct_disconnect, .begin_trans = semanage_direct_begintrans, .commit = semanage_direct_commit, .install = semanage_direct_install, .extract = semanage_direct_extract, .install_file = semanage_direct_install_file, .remove = semanage_direct_remove, .list = semanage_direct_list, .get_enabled = semanage_direct_get_enabled, .set_enabled = semanage_direct_set_enabled, .get_module_info = semanage_direct_get_module_info, .list_all = semanage_direct_list_all, .install_info = semanage_direct_install_info, .remove_key = semanage_direct_remove_key, }; int semanage_direct_is_managed(semanage_handle_t * sh) { if (semanage_check_init(sh, sh->conf->store_root_path)) goto err; if (semanage_access_check(sh) < 0) return 0; return 1; err: ERR(sh, "could not check whether policy is managed"); return STATUS_ERR; } /* Check that the module store exists, creating it if necessary. */ int semanage_direct_connect(semanage_handle_t * sh) { const char *path; struct stat sb; if (semanage_check_init(sh, sh->conf->store_root_path)) goto err; if (sh->create_store) if (semanage_create_store(sh, 1)) goto err; sh->u.direct.translock_file_fd = -1; sh->u.direct.activelock_file_fd = -1; /* set up function pointers */ sh->funcs = &direct_funcs; /* Object databases: local modifications */ if (user_base_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_USERS_BASE_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_BASE_LOCAL), semanage_user_base_dbase_local(sh)) < 0) goto err; if (user_extra_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_USERS_EXTRA_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA_LOCAL), semanage_user_extra_dbase_local(sh)) < 0) goto err; if (user_join_dbase_init(sh, semanage_user_base_dbase_local(sh), semanage_user_extra_dbase_local(sh), semanage_user_dbase_local(sh)) < 0) goto err; if (port_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_PORTS_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_PORTS_LOCAL), semanage_port_dbase_local(sh)) < 0) goto err; if (iface_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_INTERFACES_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_INTERFACES_LOCAL), semanage_iface_dbase_local(sh)) < 0) goto err; if (bool_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_BOOLEANS_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_BOOLEANS_LOCAL), semanage_bool_dbase_local(sh)) < 0) goto err; if (fcontext_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL), semanage_fcontext_dbase_local(sh)) < 0) goto err; if (fcontext_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC_HOMEDIRS), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS), semanage_fcontext_dbase_homedirs(sh)) < 0) goto err; if (seuser_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_SEUSERS_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS_LOCAL), semanage_seuser_dbase_local(sh)) < 0) goto err; if (node_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_NODES_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_NODES_LOCAL), semanage_node_dbase_local(sh)) < 0) goto err; if (ibpkey_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_IBPKEYS_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_IBPKEYS_LOCAL), semanage_ibpkey_dbase_local(sh)) < 0) goto err; if (ibendport_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_IBENDPORTS_LOCAL), semanage_path(SEMANAGE_TMP, SEMANAGE_IBENDPORTS_LOCAL), semanage_ibendport_dbase_local(sh)) < 0) goto err; /* Object databases: local modifications + policy */ if (user_base_policydb_dbase_init(sh, semanage_user_base_dbase_policy(sh)) < 0) goto err; if (user_extra_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_USERS_EXTRA), semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA), semanage_user_extra_dbase_policy(sh)) < 0) goto err; if (user_join_dbase_init(sh, semanage_user_base_dbase_policy(sh), semanage_user_extra_dbase_policy(sh), semanage_user_dbase_policy(sh)) < 0) goto err; if (port_policydb_dbase_init(sh, semanage_port_dbase_policy(sh)) < 0) goto err; if (ibpkey_policydb_dbase_init(sh, semanage_ibpkey_dbase_policy(sh)) < 0) goto err; if (ibendport_policydb_dbase_init(sh, semanage_ibendport_dbase_policy(sh)) < 0) goto err; if (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0) goto err; if (bool_policydb_dbase_init(sh, semanage_bool_dbase_policy(sh)) < 0) goto err; if (fcontext_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC), semanage_fcontext_dbase_policy(sh)) < 0) goto err; if (seuser_file_dbase_init(sh, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_SEUSERS), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS), semanage_seuser_dbase_policy(sh)) < 0) goto err; if (node_policydb_dbase_init(sh, semanage_node_dbase_policy(sh)) < 0) goto err; /* Active kernel policy */ if (bool_activedb_dbase_init(sh, semanage_bool_dbase_active(sh)) < 0) goto err; /* set the disable dontaudit value */ path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_DISABLE_DONTAUDIT); if (stat(path, &sb) == 0) sepol_set_disable_dontaudit(sh->sepolh, 1); else if (errno == ENOENT) { /* The file does not exist */ sepol_set_disable_dontaudit(sh->sepolh, 0); } else { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); goto err; } return STATUS_SUCCESS; err: ERR(sh, "could not establish direct connection"); return STATUS_ERR; } static void semanage_direct_destroy(semanage_handle_t * sh __attribute__ ((unused))) { /* do nothing */ } static int semanage_remove_tmps(semanage_handle_t *sh) { if (sh->commit_err) return 0; /* destroy sandbox if it exists */ if (semanage_remove_directory (semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL)) < 0) { if (errno != ENOENT) { ERR(sh, "Could not cleanly remove sandbox %s.", semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL)); return -1; } } /* destroy tmp policy if it exists */ if (semanage_remove_directory (semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FINAL_TOPLEVEL)) < 0) { if (errno != ENOENT) { ERR(sh, "Could not cleanly remove tmp %s.", semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FINAL_TOPLEVEL)); return -1; } } return 0; } static int semanage_direct_disconnect(semanage_handle_t *sh) { int retval = 0; /* destroy transaction and remove tmp files if no commit error */ if (sh->is_in_transaction) { retval = semanage_remove_tmps(sh); semanage_release_trans_lock(sh); } /* Release object databases: local modifications */ user_base_file_dbase_release(semanage_user_base_dbase_local(sh)); user_extra_file_dbase_release(semanage_user_extra_dbase_local(sh)); user_join_dbase_release(semanage_user_dbase_local(sh)); port_file_dbase_release(semanage_port_dbase_local(sh)); ibpkey_file_dbase_release(semanage_ibpkey_dbase_local(sh)); ibendport_file_dbase_release(semanage_ibendport_dbase_local(sh)); iface_file_dbase_release(semanage_iface_dbase_local(sh)); bool_file_dbase_release(semanage_bool_dbase_local(sh)); fcontext_file_dbase_release(semanage_fcontext_dbase_local(sh)); fcontext_file_dbase_release(semanage_fcontext_dbase_homedirs(sh)); seuser_file_dbase_release(semanage_seuser_dbase_local(sh)); node_file_dbase_release(semanage_node_dbase_local(sh)); /* Release object databases: local modifications + policy */ user_base_policydb_dbase_release(semanage_user_base_dbase_policy(sh)); user_extra_file_dbase_release(semanage_user_extra_dbase_policy(sh)); user_join_dbase_release(semanage_user_dbase_policy(sh)); port_policydb_dbase_release(semanage_port_dbase_policy(sh)); ibpkey_policydb_dbase_release(semanage_ibpkey_dbase_policy(sh)); ibendport_policydb_dbase_release(semanage_ibendport_dbase_policy(sh)); iface_policydb_dbase_release(semanage_iface_dbase_policy(sh)); bool_policydb_dbase_release(semanage_bool_dbase_policy(sh)); fcontext_file_dbase_release(semanage_fcontext_dbase_policy(sh)); seuser_file_dbase_release(semanage_seuser_dbase_policy(sh)); node_policydb_dbase_release(semanage_node_dbase_policy(sh)); /* Release object databases: active kernel policy */ bool_activedb_dbase_release(semanage_bool_dbase_active(sh)); return retval; } static int semanage_direct_begintrans(semanage_handle_t * sh) { if (semanage_get_trans_lock(sh) < 0) { return -1; } if ((semanage_make_sandbox(sh)) < 0) { return -1; } if ((semanage_make_final(sh)) < 0) { return -1; } return 0; } /********************* utility functions *********************/ /* Takes a module stored in 'module_data' and parses its headers. * Sets reference variables 'module_name' to module's name, and * 'version' to module's version. The caller is responsible for * free()ing 'module_name', and 'version'; they will be * set to NULL upon entering this function. Returns 0 on success, -1 * if out of memory. */ static int parse_module_headers(semanage_handle_t * sh, char *module_data, size_t data_len, char **module_name, char **version) { struct sepol_policy_file *pf; int file_type; *module_name = *version = NULL; if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); return -1; } sepol_policy_file_set_mem(pf, module_data, data_len); sepol_policy_file_set_handle(pf, sh->sepolh); if (module_data != NULL && data_len > 0) sepol_module_package_info(pf, &file_type, module_name, version); sepol_policy_file_free(pf); return 0; } #include #include #include #include /* bzip() a data to a file, returning the total number of compressed bytes * in the file. Returns -1 if file could not be compressed. */ static ssize_t bzip(semanage_handle_t *sh, const char *filename, char *data, size_t num_bytes) { BZFILE* b; size_t size = 1<<16; int bzerror; size_t total = 0; size_t len = 0; FILE *f; if ((f = fopen(filename, "wb")) == NULL) { return -1; } if (!sh->conf->bzip_blocksize) { if (fwrite(data, 1, num_bytes, f) < num_bytes) { fclose(f); return -1; } fclose(f); return num_bytes; } b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0); if (bzerror != BZ_OK) { BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 ); return -1; } while ( num_bytes > total ) { if (num_bytes - total > size) { len = size; } else { len = num_bytes - total; } BZ2_bzWrite ( &bzerror, b, &data[total], len ); if (bzerror == BZ_IO_ERROR) { BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 ); return -1; } total += len; } BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 ); fclose(f); if (bzerror == BZ_IO_ERROR) { return -1; } return total; } #define BZ2_MAGICSTR "BZh" #define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1) /* bunzip() a file to '*data', returning the total number of uncompressed bytes * in the file. Returns -1 if file could not be decompressed. */ ssize_t bunzip(semanage_handle_t *sh, FILE *f, char **data) { BZFILE* b = NULL; size_t nBuf; char* buf = NULL; size_t size = 1<<18; size_t bufsize = size; int bzerror; size_t total=0; char* uncompress = NULL; char* tmpalloc = NULL; int ret = -1; buf = malloc(bufsize); if (buf == NULL) { ERR(sh, "Failure allocating memory."); goto exit; } /* Check if the file is bzipped */ bzerror = fread(buf, 1, BZ2_MAGICLEN, f); rewind(f); if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) { goto exit; } b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 ); if ( bzerror != BZ_OK ) { ERR(sh, "Failure opening bz2 archive."); goto exit; } uncompress = malloc(size); if (uncompress == NULL) { ERR(sh, "Failure allocating memory."); goto exit; } while ( bzerror == BZ_OK) { nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize); if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) { if (total + nBuf > size) { size *= 2; tmpalloc = realloc(uncompress, size); if (tmpalloc == NULL) { ERR(sh, "Failure allocating memory."); goto exit; } uncompress = tmpalloc; } memcpy(&uncompress[total], buf, nBuf); total += nBuf; } } if ( bzerror != BZ_STREAM_END ) { ERR(sh, "Failure reading bz2 archive."); goto exit; } ret = total; *data = uncompress; exit: BZ2_bzReadClose ( &bzerror, b ); free(buf); if ( ret < 0 ) { free(uncompress); } return ret; } /* mmap() a file to '*data', * If the file is bzip compressed map_file will uncompress * the file into '*data'. * Returns the total number of bytes in memory . * Returns -1 if file could not be opened or mapped. */ static ssize_t map_file(semanage_handle_t *sh, const char *path, char **data, int *compressed) { ssize_t size = -1; char *uncompress; int fd = -1; FILE *file = NULL; fd = open(path, O_RDONLY); if (fd == -1) { ERR(sh, "Unable to open %s\n", path); return -1; } file = fdopen(fd, "r"); if (file == NULL) { ERR(sh, "Unable to open %s\n", path); close(fd); return -1; } if ((size = bunzip(sh, file, &uncompress)) > 0) { *data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); if (*data == MAP_FAILED) { free(uncompress); fclose(file); return -1; } else { memcpy(*data, uncompress, size); } free(uncompress); *compressed = 1; } else { struct stat sb; if (fstat(fd, &sb) == -1 || (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { size = -1; } else { size = sb.st_size; } *compressed = 0; } fclose(file); return size; } /* Writes a block of data to a file. Returns 0 on success, -1 on * error. */ static int write_file(semanage_handle_t * sh, const char *filename, char *data, size_t num_bytes) { int out; if ((out = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) { ERR(sh, "Could not open %s for writing.", filename); return -1; } if (write(out, data, num_bytes) == -1) { ERR(sh, "Error while writing to %s.", filename); close(out); return -1; } close(out); return 0; } static int semanage_direct_update_user_extra(semanage_handle_t * sh, cil_db_t *cildb) { const char *ofilename = NULL; int retval = -1; char *data = NULL; size_t size = 0; dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh); retval = cil_userprefixes_to_string(cildb, &data, &size); if (retval != SEPOL_OK) { goto cleanup; } if (size > 0) { /* * Write the users_extra entries from CIL modules. * This file is used as our baseline when we do not require * re-linking. */ ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA_LINKED); if (ofilename == NULL) { retval = -1; goto cleanup; } retval = write_file(sh, ofilename, data, size); if (retval < 0) goto cleanup; /* * Write the users_extra file; users_extra.local * will be merged into this file. */ ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA); if (ofilename == NULL) { retval = -1; goto cleanup; } retval = write_file(sh, ofilename, data, size); if (retval < 0) goto cleanup; pusers_extra->dtable->drop_cache(pusers_extra->dbase); } else { retval = pusers_extra->dtable->clear(sh, pusers_extra->dbase); } cleanup: free(data); return retval; } static int semanage_direct_update_seuser(semanage_handle_t * sh, cil_db_t *cildb) { const char *ofilename = NULL; int retval = -1; char *data = NULL; size_t size = 0; dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh); retval = cil_selinuxusers_to_string(cildb, &data, &size); if (retval != SEPOL_OK) { goto cleanup; } if (size > 0) { /* * Write the seusers entries from CIL modules. * This file is used as our baseline when we do not require * re-linking. */ ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS_LINKED); if (ofilename == NULL) { retval = -1; goto cleanup; } retval = write_file(sh, ofilename, data, size); if (retval < 0) goto cleanup; /* * Write the seusers file; seusers.local will be merged into * this file. */ ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS); if (ofilename == NULL) { retval = -1; goto cleanup; } retval = write_file(sh, ofilename, data, size); if (retval < 0) goto cleanup; pseusers->dtable->drop_cache(pseusers->dbase); } else { retval = pseusers->dtable->clear(sh, pseusers->dbase); } cleanup: free(data); return retval; } static int read_from_pipe_to_data(semanage_handle_t *sh, size_t initial_len, int fd, char **out_data_read, size_t *out_read_len) { size_t max_len = initial_len; size_t read_len = 0; size_t data_read_len = 0; char *data_read = NULL; if (max_len <= 0) { max_len = 1; } data_read = malloc(max_len * sizeof(*data_read)); if (data_read == NULL) { ERR(sh, "Failed to malloc, out of memory.\n"); return -1; } while ((read_len = read(fd, data_read + data_read_len, max_len - data_read_len)) > 0) { data_read_len += read_len; if (data_read_len == max_len) { max_len *= 2; data_read = realloc(data_read, max_len); if (data_read == NULL) { ERR(sh, "Failed to realloc, out of memory.\n"); return -1; } } } *out_read_len = data_read_len; *out_data_read = data_read; return 0; } static int semanage_pipe_data(semanage_handle_t *sh, char *path, char *in_data, size_t in_data_len, char **out_data, size_t *out_data_len, char **err_data, size_t *err_data_len) { int input_fd[2] = {-1, -1}; int output_fd[2] = {-1, -1}; int err_fd[2] = {-1, -1}; pid_t pid; char *data_read = NULL; char *err_data_read = NULL; int retval; int status = 0; size_t initial_len; size_t data_read_len = 0; size_t err_data_read_len = 0; struct sigaction old_signal; struct sigaction new_signal; new_signal.sa_handler = SIG_IGN; sigemptyset(&new_signal.sa_mask); new_signal.sa_flags = 0; /* This is needed in case the read end of input_fd is closed causing a SIGPIPE signal to be sent. * If SIGPIPE is not caught, the signal will cause semanage to terminate immediately. The sigaction below * creates a new_signal that ignores SIGPIPE allowing the write to exit cleanly. * * Another sigaction is called in cleanup to restore the original behavior when a SIGPIPE is received. */ sigaction(SIGPIPE, &new_signal, &old_signal); retval = pipe(input_fd); if (retval == -1) { ERR(sh, "Unable to create pipe for input pipe: %s\n", strerror(errno)); goto cleanup; } retval = pipe(output_fd); if (retval == -1) { ERR(sh, "Unable to create pipe for output pipe: %s\n", strerror(errno)); goto cleanup; } retval = pipe(err_fd); if (retval == -1) { ERR(sh, "Unable to create pipe for error pipe: %s\n", strerror(errno)); goto cleanup; } pid = fork(); if (pid == -1) { ERR(sh, "Unable to fork from parent: %s.", strerror(errno)); retval = -1; goto cleanup; } else if (pid == 0) { retval = dup2(input_fd[PIPE_READ], STDIN_FILENO); if (retval == -1) { ERR(sh, "Unable to dup2 input pipe: %s\n", strerror(errno)); goto cleanup; } retval = dup2(output_fd[PIPE_WRITE], STDOUT_FILENO); if (retval == -1) { ERR(sh, "Unable to dup2 output pipe: %s\n", strerror(errno)); goto cleanup; } retval = dup2(err_fd[PIPE_WRITE], STDERR_FILENO); if (retval == -1) { ERR(sh, "Unable to dup2 error pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(input_fd[PIPE_WRITE]); if (retval == -1) { ERR(sh, "Unable to close input pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(output_fd[PIPE_READ]); if (retval == -1) { ERR(sh, "Unable to close output pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(err_fd[PIPE_READ]); if (retval == -1) { ERR(sh, "Unable to close error pipe: %s\n", strerror(errno)); goto cleanup; } retval = execl(path, path, NULL); if (retval == -1) { ERR(sh, "Unable to execute %s : %s\n", path, strerror(errno)); _exit(EXIT_FAILURE); } } else { retval = close(input_fd[PIPE_READ]); input_fd[PIPE_READ] = -1; if (retval == -1) { ERR(sh, "Unable to close read end of input pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(output_fd[PIPE_WRITE]); output_fd[PIPE_WRITE] = -1; if (retval == -1) { ERR(sh, "Unable to close write end of output pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(err_fd[PIPE_WRITE]); err_fd[PIPE_WRITE] = -1; if (retval == -1) { ERR(sh, "Unable to close write end of error pipe: %s\n", strerror(errno)); goto cleanup; } retval = write(input_fd[PIPE_WRITE], in_data, in_data_len); if (retval == -1) { ERR(sh, "Failed to write data to input pipe: %s\n", strerror(errno)); goto cleanup; } retval = close(input_fd[PIPE_WRITE]); input_fd[PIPE_WRITE] = -1; if (retval == -1) { ERR(sh, "Unable to close write end of input pipe: %s\n", strerror(errno)); goto cleanup; } initial_len = 1 << 17; retval = read_from_pipe_to_data(sh, initial_len, output_fd[PIPE_READ], &data_read, &data_read_len); if (retval != 0) { goto cleanup; } retval = close(output_fd[PIPE_READ]); output_fd[PIPE_READ] = -1; if (retval == -1) { ERR(sh, "Unable to close read end of output pipe: %s\n", strerror(errno)); goto cleanup; } initial_len = 1 << 9; retval = read_from_pipe_to_data(sh, initial_len, err_fd[PIPE_READ], &err_data_read, &err_data_read_len); if (retval != 0) { goto cleanup; } retval = close(err_fd[PIPE_READ]); err_fd[PIPE_READ] = -1; if (retval == -1) { ERR(sh, "Unable to close read end of error pipe: %s\n", strerror(errno)); goto cleanup; } if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) { ERR(sh, "Child process %s did not exit cleanly.", path); retval = -1; goto cleanup; } if (WEXITSTATUS(status) != 0) { ERR(sh, "Child process %s failed with code: %d.", path, WEXITSTATUS(status)); retval = -1; goto cleanup; } } retval = 0; cleanup: sigaction(SIGPIPE, &old_signal, NULL); if (data_read != NULL) { *out_data = data_read; *out_data_len = data_read_len; } if (err_data_read != NULL) { *err_data = err_data_read; *err_data_len = err_data_read_len; } if (output_fd[PIPE_READ] != -1) { close(output_fd[PIPE_READ]); } if (output_fd[PIPE_WRITE] != -1) { close(output_fd[PIPE_WRITE]); } if (err_fd[PIPE_READ] != -1) { close(err_fd[PIPE_READ]); } if (err_fd[PIPE_WRITE] != -1) { close(err_fd[PIPE_WRITE]); } if (input_fd[PIPE_READ] != -1) { close(input_fd[PIPE_READ]); } if (input_fd[PIPE_WRITE] != -1) { close(input_fd[PIPE_WRITE]); } return retval; } static int semanage_direct_write_langext(semanage_handle_t *sh, const char *lang_ext, const semanage_module_info_t *modinfo) { int ret = -1; char fn[PATH_MAX]; FILE *fp = NULL; ret = semanage_module_get_path(sh, modinfo, SEMANAGE_MODULE_PATH_LANG_EXT, fn, sizeof(fn)); if (ret != 0) { goto cleanup; } fp = fopen(fn, "w"); if (fp == NULL) { ERR(sh, "Unable to open %s module ext file.", modinfo->name); ret = -1; goto cleanup; } if (fputs(lang_ext, fp) < 0) { ERR(sh, "Unable to write %s module ext file.", modinfo->name); ret = -1; goto cleanup; } if (fclose(fp) != 0) { ERR(sh, "Unable to close %s module ext file.", modinfo->name); ret = -1; goto cleanup; } fp = NULL; ret = 0; cleanup: if (fp != NULL) fclose(fp); return ret; } static int semanage_compile_module(semanage_handle_t *sh, semanage_module_info_t *modinfo) { char cil_path[PATH_MAX]; char hll_path[PATH_MAX]; char *compiler_path = NULL; char *cil_data = NULL; char *err_data = NULL; char *hll_data = NULL; char *start = NULL; char *end = NULL; ssize_t hll_data_len = 0; ssize_t bzip_status; int status = 0; int compressed; size_t cil_data_len = 0; size_t err_data_len = 0; if (!strcasecmp(modinfo->lang_ext, "cil")) { goto cleanup; } status = semanage_get_hll_compiler_path(sh, modinfo->lang_ext, &compiler_path); if (status != 0) { goto cleanup; } status = semanage_module_get_path( sh, modinfo, SEMANAGE_MODULE_PATH_CIL, cil_path, sizeof(cil_path)); if (status != 0) { goto cleanup; } status = semanage_module_get_path( sh, modinfo, SEMANAGE_MODULE_PATH_HLL, hll_path, sizeof(hll_path)); if (status != 0) { goto cleanup; } if ((hll_data_len = map_file(sh, hll_path, &hll_data, &compressed)) <= 0) { ERR(sh, "Unable to read file %s\n", hll_path); status = -1; goto cleanup; } status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len); if (err_data_len > 0) { for (start = end = err_data; end < err_data + err_data_len; end++) { if (*end == '\n') { fprintf(stderr, "%s: ", modinfo->name); fwrite(start, 1, end - start + 1, stderr); start = end + 1; } } if (end != start) { fprintf(stderr, "%s: ", modinfo->name); fwrite(start, 1, end - start, stderr); fprintf(stderr, "\n"); } } if (status != 0) { goto cleanup; } bzip_status = bzip(sh, cil_path, cil_data, cil_data_len); if (bzip_status == -1) { ERR(sh, "Failed to bzip %s\n", cil_path); status = -1; goto cleanup; } if (sh->conf->remove_hll == 1) { status = unlink(hll_path); if (status != 0) { ERR(sh, "Error while removing HLL file %s: %s", hll_path, strerror(errno)); goto cleanup; } status = semanage_direct_write_langext(sh, "cil", modinfo); if (status != 0) { goto cleanup; } } cleanup: if (hll_data_len > 0) { munmap(hll_data, hll_data_len); } free(cil_data); free(err_data); free(compiler_path); return status; } static int semanage_compile_hll_modules(semanage_handle_t *sh, semanage_module_info_t *modinfos, int num_modinfos) { int status = 0; int i; char cil_path[PATH_MAX]; struct stat sb; assert(sh); assert(modinfos); for (i = 0; i < num_modinfos; i++) { status = semanage_module_get_path( sh, &modinfos[i], SEMANAGE_MODULE_PATH_CIL, cil_path, sizeof(cil_path)); if (status != 0) { goto cleanup; } if (semanage_get_ignore_module_cache(sh) == 0 && (status = stat(cil_path, &sb)) == 0) { continue; } if (status != 0 && errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", cil_path, strerror(errno)); goto cleanup; //an error in the "stat" call } status = semanage_compile_module(sh, &modinfos[i]); if (status < 0) { goto cleanup; } } status = 0; cleanup: return status; } /* Copies a file from src to dst. If dst already exists then * overwrite it. If source doesn't exist then return success. * Returns 0 on success, -1 on error. */ static int copy_file_if_exists(const char *src, const char *dst, mode_t mode){ int rc = semanage_copy_file(src, dst, mode); return (rc < 0 && errno != ENOENT) ? rc : 0; } /********************* direct API functions ********************/ /* Commits all changes in sandbox to the actual kernel policy. * Returns commit number on success, -1 on error. */ static int semanage_direct_commit(semanage_handle_t * sh) { char **mod_filenames = NULL; char *fc_buffer = NULL; size_t fc_buffer_len = 0; const char *ofilename = NULL; const char *path; int retval = -1, num_modinfos = 0, i; sepol_policydb_t *out = NULL; struct cil_db *cildb = NULL; semanage_module_info_t *modinfos = NULL; mode_t mask = umask(0077); struct stat sb; int do_rebuild, do_write_kernel, do_install; int fcontexts_modified, ports_modified, seusers_modified, disable_dontaudit, preserve_tunables, ibpkeys_modified, ibendports_modified; dbase_config_t *users = semanage_user_dbase_local(sh); dbase_config_t *users_base = semanage_user_base_dbase_local(sh); dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh); dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh); dbase_config_t *ports = semanage_port_dbase_local(sh); dbase_config_t *pports = semanage_port_dbase_policy(sh); dbase_config_t *ibpkeys = semanage_ibpkey_dbase_local(sh); dbase_config_t *pibpkeys = semanage_ibpkey_dbase_policy(sh); dbase_config_t *ibendports = semanage_ibendport_dbase_local(sh); dbase_config_t *pibendports = semanage_ibendport_dbase_policy(sh); dbase_config_t *bools = semanage_bool_dbase_local(sh); dbase_config_t *pbools = semanage_bool_dbase_policy(sh); dbase_config_t *ifaces = semanage_iface_dbase_local(sh); dbase_config_t *pifaces = semanage_iface_dbase_policy(sh); dbase_config_t *nodes = semanage_node_dbase_local(sh); dbase_config_t *pnodes = semanage_node_dbase_policy(sh); dbase_config_t *fcontexts = semanage_fcontext_dbase_local(sh); dbase_config_t *pfcontexts = semanage_fcontext_dbase_policy(sh); dbase_config_t *seusers = semanage_seuser_dbase_local(sh); dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh); /* Modified flags that we need to use more than once. */ ports_modified = ports->dtable->is_modified(ports->dbase); ibpkeys_modified = ibpkeys->dtable->is_modified(ibpkeys->dbase); ibendports_modified = ibendports->dtable->is_modified(ibendports->dbase); seusers_modified = seusers->dtable->is_modified(seusers->dbase); fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase); /* Rebuild if explicitly requested or any module changes occurred. */ do_rebuild = sh->do_rebuild | sh->modules_modified; /* Create or remove the disable_dontaudit flag file. */ path = semanage_path(SEMANAGE_TMP, SEMANAGE_DISABLE_DONTAUDIT); if (stat(path, &sb) == 0) do_rebuild |= !(sepol_get_disable_dontaudit(sh->sepolh) == 1); else if (errno == ENOENT) { /* The file does not exist */ do_rebuild |= (sepol_get_disable_dontaudit(sh->sepolh) == 1); } else { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); retval = -1; goto cleanup; } if (sepol_get_disable_dontaudit(sh->sepolh) == 1) { FILE *touch; touch = fopen(path, "w"); if (touch != NULL) { if (fclose(touch) != 0) { ERR(sh, "Error attempting to create disable_dontaudit flag."); goto cleanup; } } else { ERR(sh, "Error attempting to create disable_dontaudit flag."); goto cleanup; } } else { if (remove(path) == -1 && errno != ENOENT) { ERR(sh, "Error removing the disable_dontaudit flag."); goto cleanup; } } /* Create or remove the preserve_tunables flag file. */ path = semanage_path(SEMANAGE_TMP, SEMANAGE_PRESERVE_TUNABLES); if (stat(path, &sb) == 0) do_rebuild |= !(sepol_get_preserve_tunables(sh->sepolh) == 1); else if (errno == ENOENT) { /* The file does not exist */ do_rebuild |= (sepol_get_preserve_tunables(sh->sepolh) == 1); } else { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); retval = -1; goto cleanup; } if (sepol_get_preserve_tunables(sh->sepolh) == 1) { FILE *touch; touch = fopen(path, "w"); if (touch != NULL) { if (fclose(touch) != 0) { ERR(sh, "Error attempting to create preserve_tunable flag."); goto cleanup; } } else { ERR(sh, "Error attempting to create preserve_tunable flag."); goto cleanup; } } else { if (remove(path) == -1 && errno != ENOENT) { ERR(sh, "Error removing the preserve_tunables flag."); goto cleanup; } } /* Before we do anything else, flush the join to its component parts. * This *does not* flush to disk automatically */ if (users->dtable->is_modified(users->dbase)) { retval = users->dtable->flush(sh, users->dbase); if (retval < 0) goto cleanup; } /* * This is for systems that have already migrated with an older version * of semanage_migrate_store. The older version did not copy * policy.kern so the policy binary must be rebuilt here. * This also ensures that any linked files that are required * in order to skip re-linking are present; otherwise, we force * a rebuild. */ if (!do_rebuild) { int files[] = {SEMANAGE_STORE_KERNEL, SEMANAGE_STORE_FC, SEMANAGE_STORE_SEUSERS, SEMANAGE_LINKED, SEMANAGE_SEUSERS_LINKED, SEMANAGE_USERS_EXTRA_LINKED}; for (i = 0; i < (int) ARRAY_SIZE(files); i++) { path = semanage_path(SEMANAGE_TMP, files[i]); if (stat(path, &sb) != 0) { if (errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); retval = -1; goto cleanup; } do_rebuild = 1; goto rebuild; } } } rebuild: /* * Now that we know whether or not a rebuild is required, * we can determine what else needs to be done. * We need to write the kernel policy if we are rebuilding * or if any other policy component that lives in the kernel * policy has been modified. * We need to install the policy files if any of the managed files * that live under /etc/selinux (kernel policy, seusers, file contexts) * will be modified. */ do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified | ibendports_modified | bools->dtable->is_modified(bools->dbase) | ifaces->dtable->is_modified(ifaces->dbase) | nodes->dtable->is_modified(nodes->dbase) | users->dtable->is_modified(users_base->dbase); do_install = do_write_kernel | seusers_modified | fcontexts_modified; /* * If there were policy changes, or explicitly requested, or * any required files are missing, rebuild the policy. */ if (do_rebuild) { /* =================== Module expansion =============== */ retval = semanage_get_active_modules(sh, &modinfos, &num_modinfos); if (retval < 0) { goto cleanup; } if (num_modinfos == 0) { goto cleanup; } retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos); if (retval < 0) { ERR(sh, "Failed to compile hll files into cil files.\n"); goto cleanup; } retval = semanage_get_cil_paths(sh, modinfos, num_modinfos, &mod_filenames); if (retval < 0) goto cleanup; retval = semanage_verify_modules(sh, mod_filenames, num_modinfos); if (retval < 0) goto cleanup; cil_db_init(&cildb); disable_dontaudit = sepol_get_disable_dontaudit(sh->sepolh); preserve_tunables = sepol_get_preserve_tunables(sh->sepolh); cil_set_disable_dontaudit(cildb, disable_dontaudit); cil_set_disable_neverallow(cildb, !(sh->conf->expand_check)); cil_set_preserve_tunables(cildb, preserve_tunables); cil_set_target_platform(cildb, sh->conf->target_platform); cil_set_policy_version(cildb, sh->conf->policyvers); if (sh->conf->handle_unknown != -1) { cil_set_handle_unknown(cildb, sh->conf->handle_unknown); } retval = semanage_load_files(sh, cildb, mod_filenames, num_modinfos); if (retval < 0) { goto cleanup; } retval = cil_compile(cildb); if (retval < 0) goto cleanup; retval = cil_build_policydb(cildb, &out); if (retval < 0) goto cleanup; /* File Contexts */ retval = cil_filecons_to_string(cildb, &fc_buffer, &fc_buffer_len); if (retval < 0) goto cleanup; /* Write the contexts (including template contexts) to a single file. */ ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL); if (ofilename == NULL) { retval = -1; goto cleanup; } retval = write_file(sh, ofilename, fc_buffer, fc_buffer_len); if (retval < 0) goto cleanup; /* Split complete and template file contexts into their separate files. */ retval = semanage_split_fc(sh); if (retval < 0) goto cleanup; /* remove FC_TMPL now that it is now longer needed */ unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL)); pfcontexts->dtable->drop_cache(pfcontexts->dbase); /* SEUsers */ retval = semanage_direct_update_seuser(sh, cildb); if (retval < 0) goto cleanup; /* User Extra */ retval = semanage_direct_update_user_extra(sh, cildb); if (retval < 0) goto cleanup; cil_db_destroy(&cildb); /* Write the linked policy before merging local changes. */ retval = semanage_write_policydb(sh, out, SEMANAGE_LINKED); if (retval < 0) goto cleanup; } else { /* Load the existing linked policy, w/o local changes */ retval = sepol_policydb_create(&out); if (retval < 0) goto cleanup; retval = semanage_read_policydb(sh, out, SEMANAGE_LINKED); if (retval < 0) goto cleanup; path = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS_LINKED); if (stat(path, &sb) == 0) { retval = semanage_copy_file(path, semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS), 0); if (retval < 0) goto cleanup; pseusers->dtable->drop_cache(pseusers->dbase); } else if (errno == ENOENT) { /* The file does not exist */ pseusers->dtable->clear(sh, pseusers->dbase); } else { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); retval = -1; goto cleanup; } path = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA_LINKED); if (stat(path, &sb) == 0) { retval = semanage_copy_file(path, semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA), 0); if (retval < 0) goto cleanup; pusers_extra->dtable->drop_cache(pusers_extra->dbase); } else if (errno == ENOENT) { /* The file does not exist */ pusers_extra->dtable->clear(sh, pusers_extra->dbase); } else { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); retval = -1; goto cleanup; } } /* Attach our databases to the policydb we just created or loaded. */ dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pibpkeys->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pibendports->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out); dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out); /* Merge local changes */ retval = semanage_base_merge_components(sh); if (retval < 0) goto cleanup; if (do_write_kernel) { /* Write new kernel policy. */ retval = semanage_write_policydb(sh, out, SEMANAGE_STORE_KERNEL); if (retval < 0) goto cleanup; /* Run the kernel policy verifier, if any. */ retval = semanage_verify_kernel(sh); if (retval < 0) goto cleanup; } /* ======= Post-process: Validate non-policydb components ===== */ /* Validate local modifications to file contexts. * Note: those are still cached, even though they've been * merged into the main file_contexts. We won't check the * large file_contexts - checked at compile time */ if (do_rebuild || fcontexts_modified) { retval = semanage_fcontext_validate_local(sh, out); if (retval < 0) goto cleanup; } /* Validate local seusers against policy */ if (do_rebuild || seusers_modified) { retval = semanage_seuser_validate_local(sh, out); if (retval < 0) goto cleanup; } /* Validate local ports for overlap */ if (do_rebuild || ports_modified) { retval = semanage_port_validate_local(sh); if (retval < 0) goto cleanup; } /* Validate local ibpkeys for overlap */ if (do_rebuild || ibpkeys_modified) { retval = semanage_ibpkey_validate_local(sh); if (retval < 0) goto cleanup; } /* Validate local ibendports */ if (do_rebuild || ibendports_modified) { retval = semanage_ibendport_validate_local(sh); if (retval < 0) goto cleanup; } /* ================== Write non-policydb components ========= */ /* Commit changes to components */ retval = semanage_commit_components(sh); if (retval < 0) goto cleanup; retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL), sh->conf->file_mode); if (retval < 0) { goto cleanup; } retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL), sh->conf->file_mode); if (retval < 0) { goto cleanup; } retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC), sh->conf->file_mode); if (retval < 0) { goto cleanup; } retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_SEUSERS), sh->conf->file_mode); if (retval < 0) { goto cleanup; } /* run genhomedircon if its enabled, this should be the last operation * which requires the out policydb */ if (!sh->conf->disable_genhomedircon) { if (out){ if ((retval = semanage_genhomedircon(sh, out, sh->conf->usepasswd, sh->conf->ignoredirs)) != 0) { ERR(sh, "semanage_genhomedircon returned error code %d.", retval); goto cleanup; } /* file_contexts.homedirs was created in SEMANAGE_TMP store */ retval = semanage_copy_file( semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS), sh->conf->file_mode); if (retval < 0) { goto cleanup; } } } else { WARN(sh, "WARNING: genhomedircon is disabled. \ See /etc/selinux/semanage.conf if you need to enable it."); } /* free out, if we don't free it before calling semanage_install_sandbox * then fork() may fail on low memory machines */ sepol_policydb_free(out); out = NULL; if (do_install) retval = semanage_install_sandbox(sh); cleanup: for (i = 0; i < num_modinfos; i++) { semanage_module_info_destroy(sh, &modinfos[i]); } free(modinfos); for (i = 0; mod_filenames != NULL && i < num_modinfos; i++) { free(mod_filenames[i]); } /* Detach from policydb, so it can be freed */ dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase); dbase_policydb_detach((dbase_policydb_t *) pports->dbase); dbase_policydb_detach((dbase_policydb_t *) pibpkeys->dbase); dbase_policydb_detach((dbase_policydb_t *) pibendports->dbase); dbase_policydb_detach((dbase_policydb_t *) pifaces->dbase); dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase); dbase_policydb_detach((dbase_policydb_t *) pbools->dbase); free(mod_filenames); sepol_policydb_free(out); cil_db_destroy(&cildb); free(fc_buffer); /* Set commit_err so other functions can detect any errors. Note that * retval > 0 will be the commit number. */ if (retval < 0) sh->commit_err = retval; if (semanage_remove_tmps(sh) != 0) retval = -1; semanage_release_trans_lock(sh); umask(mask); return retval; } /* Writes a module to the sandbox's module directory, overwriting any * previous module stored within. Note that module data are not * free()d by this function; caller is responsible for deallocating it * if necessary. Returns 0 on success, -1 if out of memory, -2 if the * data does not represent a valid module file, -3 if error while * writing file. */ static int semanage_direct_install(semanage_handle_t * sh, char *data, size_t data_len, const char *module_name, const char *lang_ext) { int status = 0; int ret = 0; semanage_module_info_t modinfo; ret = semanage_module_info_init(sh, &modinfo); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_priority(sh, &modinfo, sh->priority); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_name(sh, &modinfo, module_name); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_lang_ext(sh, &modinfo, lang_ext); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_enabled(sh, &modinfo, -1); if (ret != 0) { status = -1; goto cleanup; } status = semanage_direct_install_info(sh, &modinfo, data, data_len); cleanup: semanage_module_info_destroy(sh, &modinfo); return status; } /* Attempts to link a module to the sandbox's module directory, unlinking any * previous module stored within. Returns 0 on success, -1 if out of memory, -2 if the * data does not represent a valid module file, -3 if error while * writing file. */ static int semanage_direct_install_file(semanage_handle_t * sh, const char *install_filename) { int retval = -1; char *data = NULL; ssize_t data_len = 0; int compressed = 0; char *path = NULL; char *filename; char *lang_ext = NULL; char *module_name = NULL; char *separator; char *version = NULL; if ((data_len = map_file(sh, install_filename, &data, &compressed)) <= 0) { ERR(sh, "Unable to read file %s\n", install_filename); retval = -1; goto cleanup; } path = strdup(install_filename); if (path == NULL) { ERR(sh, "No memory available for strdup.\n"); retval = -1; goto cleanup; } filename = basename(path); if (compressed) { separator = strrchr(filename, '.'); if (separator == NULL) { ERR(sh, "Compressed module does not have a valid extension."); retval = -1; goto cleanup; } *separator = '\0'; lang_ext = separator + 1; } separator = strrchr(filename, '.'); if (separator == NULL) { if (lang_ext == NULL) { ERR(sh, "Module does not have a valid extension."); retval = -1; goto cleanup; } } else { *separator = '\0'; lang_ext = separator + 1; } if (strcmp(lang_ext, "pp") == 0) { retval = parse_module_headers(sh, data, data_len, &module_name, &version); free(version); if (retval != 0) goto cleanup; } if (module_name == NULL) { module_name = strdup(filename); if (module_name == NULL) { ERR(sh, "No memory available for module_name.\n"); retval = -1; goto cleanup; } } else if (strcmp(module_name, filename) != 0) { fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", install_filename, module_name, filename); } retval = semanage_direct_install(sh, data, data_len, module_name, lang_ext); cleanup: if (data_len > 0) munmap(data, data_len); free(module_name); free(path); return retval; } static int semanage_direct_extract(semanage_handle_t * sh, semanage_module_key_t *modkey, int extract_cil, void **mapped_data, size_t *data_len, semanage_module_info_t **modinfo) { char module_path[PATH_MAX]; char input_file[PATH_MAX]; enum semanage_module_path_type file_type; int rc = -1; semanage_module_info_t *_modinfo = NULL; ssize_t _data_len; char *_data; int compressed; struct stat sb; /* get path of module */ rc = semanage_module_get_path( sh, (const semanage_module_info_t *)modkey, SEMANAGE_MODULE_PATH_NAME, module_path, sizeof(module_path)); if (rc != 0) { goto cleanup; } if (stat(module_path, &sb) != 0) { ERR(sh, "Unable to access %s: %s\n", module_path, strerror(errno)); rc = -1; goto cleanup; } rc = semanage_module_get_module_info(sh, modkey, &_modinfo); if (rc != 0) { goto cleanup; } if (extract_cil || strcmp(_modinfo->lang_ext, "cil") == 0) { file_type = SEMANAGE_MODULE_PATH_CIL; } else { file_type = SEMANAGE_MODULE_PATH_HLL; } /* get path of what to extract */ rc = semanage_module_get_path( sh, _modinfo, file_type, input_file, sizeof(input_file)); if (rc != 0) { goto cleanup; } if (extract_cil == 1 && strcmp(_modinfo->lang_ext, "cil") && stat(input_file, &sb) != 0) { if (errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", input_file, strerror(errno)); rc = -1; goto cleanup; } rc = semanage_compile_module(sh, _modinfo); if (rc < 0) { goto cleanup; } } _data_len = map_file(sh, input_file, &_data, &compressed); if (_data_len <= 0) { ERR(sh, "Error mapping file: %s", input_file); rc = -1; goto cleanup; } *modinfo = _modinfo; *data_len = (size_t)_data_len; *mapped_data = _data; cleanup: if (rc != 0) { semanage_module_info_destroy(sh, _modinfo); free(_modinfo); } return rc; } /* Removes a module from the sandbox. Returns 0 on success, -1 if out * of memory, -2 if module not found or could not be removed. */ static int semanage_direct_remove(semanage_handle_t * sh, char *module_name) { int status = 0; int ret = 0; semanage_module_key_t modkey; ret = semanage_module_key_init(sh, &modkey); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_key_set_priority(sh, &modkey, sh->priority); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_key_set_name(sh, &modkey, module_name); if (ret != 0) { status = -1; goto cleanup; } status = semanage_direct_remove_key(sh, &modkey); cleanup: return status; } /* Allocate an array of module_info structures for each readable * module within the store. Note that if the calling program has * already begun a transaction then this function will get a list of * modules within the sandbox. The caller is responsible for calling * semanage_module_info_datum_destroy() on each element of the array * as well as free()ing the entire list. */ static int semanage_direct_list(semanage_handle_t * sh, semanage_module_info_t ** modinfo, int *num_modules) { int i, retval = -1; *modinfo = NULL; *num_modules = 0; /* get the read lock when reading from the active (non-transaction) directory */ if (!sh->is_in_transaction) if (semanage_get_active_lock(sh) < 0) return -1; if (semanage_get_active_modules(sh, modinfo, num_modules) == -1) { goto cleanup; } if (num_modules == 0) { retval = semanage_direct_get_serial(sh); goto cleanup; } retval = semanage_direct_get_serial(sh); cleanup: if (retval < 0) { for (i = 0; i < *num_modules; i++) { semanage_module_info_destroy(sh, &(*modinfo[i])); modinfo[i] = NULL; } free(*modinfo); *modinfo = NULL; } if (!sh->is_in_transaction) { semanage_release_active_lock(sh); } return retval; } static int semanage_direct_get_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int *enabled) { assert(sh); assert(modkey); assert(enabled); int status = 0; int ret = 0; char path[PATH_MAX]; struct stat sb; semanage_module_info_t *modinfo = NULL; /* get module info */ ret = semanage_module_get_module_info( sh, modkey, &modinfo); if (ret != 0) { status = -1; goto cleanup; } /* get disabled file path */ ret = semanage_module_get_path( sh, modinfo, SEMANAGE_MODULE_PATH_DISABLED, path, sizeof(path)); if (ret != 0) { status = -1; goto cleanup; } if (stat(path, &sb) < 0) { if (errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); status = -1; goto cleanup; } *enabled = 1; } else { *enabled = 0; } cleanup: semanage_module_info_destroy(sh, modinfo); free(modinfo); return status; } static int semanage_direct_set_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int enabled) { assert(sh); assert(modkey); int status = 0; int ret = 0; char fn[PATH_MAX]; const char *path = NULL; FILE *fp = NULL; semanage_module_info_t *modinfo = NULL; mode_t mask; /* check transaction */ if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { status = -1; goto cleanup; } } /* validate name */ ret = semanage_module_validate_name(modkey->name); if (ret != 0) { errno = 0; ERR(sh, "Name %s is invalid.", modkey->name); status = -1; goto cleanup; } /* validate enabled */ ret = semanage_module_validate_enabled(enabled); if (ret != 0) { errno = 0; ERR(sh, "Enabled status %d is invalid.", enabled); status = -1; goto cleanup; } /* check for disabled path, create if missing */ path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED); ret = semanage_mkdir(sh, path); if (ret != 0) { status = -1; goto cleanup; } /* get module info */ ret = semanage_module_get_module_info( sh, modkey, &modinfo); if (ret != 0) { status = -1; goto cleanup; } /* get module disabled file */ ret = semanage_module_get_path( sh, modinfo, SEMANAGE_MODULE_PATH_DISABLED, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } switch (enabled) { case 0: /* disable the module */ mask = umask(0077); fp = fopen(fn, "w"); umask(mask); if (fp == NULL) { ERR(sh, "Unable to disable module %s", modkey->name); status = -1; goto cleanup; } if (fclose(fp) != 0) { ERR(sh, "Unable to close disabled file for module %s", modkey->name); status = -1; goto cleanup; } fp = NULL; break; case 1: /* enable the module */ if (unlink(fn) < 0) { if (errno != ENOENT) { ERR(sh, "Unable to enable module %s", modkey->name); status = -1; goto cleanup; } else { /* module already enabled */ errno = 0; } } break; case -1: /* warn about ignored setting to default */ WARN(sh, "Setting module %s to 'default' state has no effect", modkey->name); break; } cleanup: semanage_module_info_destroy(sh, modinfo); free(modinfo); if (fp != NULL) fclose(fp); return status; } int semanage_direct_access_check(semanage_handle_t * sh) { if (semanage_check_init(sh, sh->conf->store_root_path)) return -1; return semanage_store_access_check(); } int semanage_direct_mls_enabled(semanage_handle_t * sh) { sepol_policydb_t *p = NULL; int retval; retval = sepol_policydb_create(&p); if (retval < 0) goto cleanup; retval = semanage_read_policydb(sh, p, SEMANAGE_STORE_KERNEL); if (retval < 0) goto cleanup; retval = sepol_policydb_mls_enabled(p); cleanup: sepol_policydb_free(p); return retval; } static int semanage_direct_get_module_info(semanage_handle_t *sh, const semanage_module_key_t *modkey, semanage_module_info_t **modinfo) { assert(sh); assert(modkey); assert(modinfo); int status = 0; int ret = 0; char fn[PATH_MAX]; FILE *fp = NULL; size_t size = 0; struct stat sb; char *tmp = NULL; int i = 0; semanage_module_info_t *modinfos = NULL; int modinfos_len = 0; semanage_module_info_t *highest = NULL; /* check module name */ ret = semanage_module_validate_name(modkey->name); if (ret < 0) { errno = 0; ERR(sh, "Name %s is invalid.", modkey->name); status = -1; goto cleanup; } /* if priority == 0, then find the highest priority available */ if (modkey->priority == 0) { ret = semanage_direct_list_all(sh, &modinfos, &modinfos_len); if (ret != 0) { status = -1; goto cleanup; } for (i = 0; i < modinfos_len; i++) { ret = strcmp(modinfos[i].name, modkey->name); if (ret == 0) { highest = &modinfos[i]; break; } } if (highest == NULL) { status = -1; goto cleanup; } ret = semanage_module_info_create(sh, modinfo); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_clone(sh, highest, *modinfo); if (ret != 0) { status = -1; } /* skip to cleanup, module was found */ goto cleanup; } /* check module priority */ ret = semanage_module_validate_priority(modkey->priority); if (ret != 0) { errno = 0; ERR(sh, "Priority %d is invalid.", modkey->priority); status = -1; goto cleanup; } /* copy in key values */ ret = semanage_module_info_create(sh, modinfo); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_priority(sh, *modinfo, modkey->priority); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_name(sh, *modinfo, modkey->name); if (ret != 0) { status = -1; goto cleanup; } /* lookup module ext */ ret = semanage_module_get_path(sh, *modinfo, SEMANAGE_MODULE_PATH_LANG_EXT, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } fp = fopen(fn, "r"); if (fp == NULL) { ERR(sh, "Unable to open %s module lang ext file at %s.", (*modinfo)->name, fn); status = -1; goto cleanup; } /* set module ext */ if (getline(&tmp, &size, fp) < 0) { ERR(sh, "Unable to read %s module lang ext file.", (*modinfo)->name); status = -1; goto cleanup; } ret = semanage_module_info_set_lang_ext(sh, *modinfo, tmp); if (ret != 0) { status = -1; goto cleanup; } free(tmp); tmp = NULL; if (fclose(fp) != 0) { ERR(sh, "Unable to close %s module lang ext file.", (*modinfo)->name); status = -1; goto cleanup; } fp = NULL; /* lookup enabled/disabled status */ ret = semanage_module_get_path(sh, *modinfo, SEMANAGE_MODULE_PATH_DISABLED, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } /* set enabled/disabled status */ if (stat(fn, &sb) < 0) { if (errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", fn, strerror(errno)); status = -1; goto cleanup; } ret = semanage_module_info_set_enabled(sh, *modinfo, 1); if (ret != 0) { status = -1; goto cleanup; } } else { ret = semanage_module_info_set_enabled(sh, *modinfo, 0); if (ret != 0) { status = -1; goto cleanup; } } cleanup: free(tmp); if (modinfos != NULL) { for (i = 0; i < modinfos_len; i++) { semanage_module_info_destroy(sh, &modinfos[i]); } free(modinfos); } if (fp != NULL) fclose(fp); return status; } static int semanage_direct_set_module_info(semanage_handle_t *sh, const semanage_module_info_t *modinfo) { int status = 0; int ret = 0; char fn[PATH_MAX]; const char *path = NULL; int enabled = 0; semanage_module_info_t *modinfo_tmp = NULL; semanage_module_key_t modkey; ret = semanage_module_key_init(sh, &modkey); if (ret != 0) { status = -1; goto cleanup; } /* check transaction */ if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { status = -1; goto cleanup; } } /* validate module */ ret = semanage_module_info_validate(modinfo); if (ret != 0) { status = -1; goto cleanup; } sh->modules_modified = 1; /* check for modules path, create if missing */ path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES); ret = semanage_mkdir(sh, path); if (ret != 0) { status = -1; goto cleanup; } /* write priority */ ret = semanage_module_get_path(sh, modinfo, SEMANAGE_MODULE_PATH_PRIORITY, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_mkdir(sh, fn); if (ret != 0) { status = -1; goto cleanup; } /* write name */ ret = semanage_module_get_path(sh, modinfo, SEMANAGE_MODULE_PATH_NAME, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_mkdir(sh, fn); if (ret != 0) { status = -1; goto cleanup; } /* write ext */ ret = semanage_direct_write_langext(sh, modinfo->lang_ext, modinfo); if (ret != 0) { status = -1; goto cleanup; } /* write enabled/disabled status */ /* check for disabled path, create if missing */ path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED); ret = semanage_mkdir(sh, path); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_get_path(sh, modinfo, SEMANAGE_MODULE_PATH_DISABLED, fn, sizeof(fn)); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_key_set_name(sh, &modkey, modinfo->name); if (ret != 0) { status = -1; goto cleanup; } if (modinfo->enabled == -1) { /* default to enabled */ enabled = 1; /* check if a module is already installed */ ret = semanage_module_get_module_info(sh, &modkey, &modinfo_tmp); if (ret == 0) { /* set enabled status to current one */ enabled = modinfo_tmp->enabled; } } else { enabled = modinfo->enabled; } ret = semanage_module_set_enabled(sh, &modkey, enabled); if (ret != 0) { status = -1; goto cleanup; } cleanup: semanage_module_key_destroy(sh, &modkey); semanage_module_info_destroy(sh, modinfo_tmp); free(modinfo_tmp); return status; } static int semanage_priorities_filename_select(const struct dirent *d) { if (d->d_name[0] == '.' || strcmp(d->d_name, "disabled") == 0) return 0; return 1; } static int semanage_modules_filename_select(const struct dirent *d) { if (d->d_name[0] == '.') return 0; return 1; } static int semanage_direct_list_all(semanage_handle_t *sh, semanage_module_info_t **modinfos, int *modinfos_len) { assert(sh); assert(modinfos); assert(modinfos_len); int status = 0; int ret = 0; int i = 0; int j = 0; *modinfos = NULL; *modinfos_len = 0; void *tmp = NULL; const char *toplevel = NULL; struct dirent **priorities = NULL; int priorities_len = 0; char priority_path[PATH_MAX]; struct dirent **modules = NULL; int modules_len = 0; uint16_t priority = 0; semanage_module_info_t *modinfo_tmp = NULL; semanage_module_info_t modinfo; ret = semanage_module_info_init(sh, &modinfo); if (ret != 0) { status = -1; goto cleanup; } if (sh->is_in_transaction) { toplevel = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES); } else { toplevel = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES); } /* find priorities */ priorities_len = scandir(toplevel, &priorities, semanage_priorities_filename_select, versionsort); if (priorities_len == -1) { ERR(sh, "Error while scanning directory %s.", toplevel); status = -1; goto cleanup; } /* for each priority directory */ /* loop through in reverse so that highest priority is first */ for (i = priorities_len - 1; i >= 0; i--) { /* convert priority string to uint16_t */ ret = semanage_string_to_priority(priorities[i]->d_name, &priority); if (ret != 0) { status = -1; goto cleanup; } /* set our priority */ ret = semanage_module_info_set_priority(sh, &modinfo, priority); if (ret != 0) { status = -1; goto cleanup; } /* get the priority path */ ret = semanage_module_get_path(sh, &modinfo, SEMANAGE_MODULE_PATH_PRIORITY, priority_path, sizeof(priority_path)); if (ret != 0) { status = -1; goto cleanup; } /* cleanup old modules */ if (modules != NULL) { for (j = 0; j < modules_len; j++) { free(modules[j]); modules[j] = NULL; } free(modules); modules = NULL; modules_len = 0; } /* find modules at this priority */ modules_len = scandir(priority_path, &modules, semanage_modules_filename_select, versionsort); if (modules_len == -1) { ERR(sh, "Error while scanning directory %s.", priority_path); status = -1; goto cleanup; } if (modules_len == 0) continue; /* add space for modules */ tmp = realloc(*modinfos, sizeof(semanage_module_info_t) * (*modinfos_len + modules_len)); if (tmp == NULL) { ERR(sh, "Error allocating memory for module array."); status = -1; goto cleanup; } *modinfos = tmp; /* for each module directory */ for(j = 0; j < modules_len; j++) { /* set module name */ ret = semanage_module_info_set_name( sh, &modinfo, modules[j]->d_name); if (ret != 0) { status = -1; goto cleanup; } /* get module values */ ret = semanage_direct_get_module_info( sh, (const semanage_module_key_t *) (&modinfo), &modinfo_tmp); if (ret != 0) { status = -1; goto cleanup; } /* copy into array */ ret = semanage_module_info_init( sh, &((*modinfos)[*modinfos_len])); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_clone( sh, modinfo_tmp, &((*modinfos)[*modinfos_len])); if (ret != 0) { status = -1; goto cleanup; } semanage_module_info_destroy(sh, modinfo_tmp); free(modinfo_tmp); modinfo_tmp = NULL; *modinfos_len += 1; } } cleanup: semanage_module_info_destroy(sh, &modinfo); if (priorities != NULL) { for (i = 0; i < priorities_len; i++) { free(priorities[i]); } free(priorities); } if (modules != NULL) { for (i = 0; i < modules_len; i++) { free(modules[i]); } free(modules); } semanage_module_info_destroy(sh, modinfo_tmp); free(modinfo_tmp); modinfo_tmp = NULL; if (status != 0) { if (modinfos != NULL) { for (i = 0; i < *modinfos_len; i++) { semanage_module_info_destroy( sh, &(*modinfos)[i]); } free(*modinfos); *modinfos = NULL; *modinfos_len = 0; } } return status; } static int semanage_direct_install_info(semanage_handle_t *sh, const semanage_module_info_t *modinfo, char *data, size_t data_len) { assert(sh); assert(modinfo); assert(data); int status = 0; int ret = 0; int type; struct stat sb; char path[PATH_MAX]; mode_t mask = umask(0077); semanage_module_info_t *higher_info = NULL; semanage_module_key_t higher_key; ret = semanage_module_key_init(sh, &higher_key); if (ret != 0) { status = -1; goto cleanup; } /* validate module info */ ret = semanage_module_info_validate(modinfo); if (ret != 0) { ERR(sh, "%s failed module validation.\n", modinfo->name); status = -2; goto cleanup; } /* Check for higher priority module and warn if there is one as * it will override the module currently being installed. */ ret = semanage_module_key_set_name(sh, &higher_key, modinfo->name); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_direct_get_module_info(sh, &higher_key, &higher_info); if (ret == 0) { if (higher_info->priority > modinfo->priority) { errno = 0; WARN(sh, "A higher priority %s module exists at priority %d and will override the module currently being installed at priority %d.", modinfo->name, higher_info->priority, modinfo->priority); } else if (higher_info->priority < modinfo->priority) { errno = 0; INFO(sh, "Overriding %s module at lower priority %d with module at priority %d.", modinfo->name, higher_info->priority, modinfo->priority); } if (higher_info->enabled == 0 && modinfo->enabled == -1) { errno = 0; WARN(sh, "%s module will be disabled after install as there is a disabled instance of this module present in the system.", modinfo->name); } } /* set module meta data */ ret = semanage_direct_set_module_info(sh, modinfo); if (ret != 0) { status = -2; goto cleanup; } /* install module source file */ if (!strcasecmp(modinfo->lang_ext, "cil")) { type = SEMANAGE_MODULE_PATH_CIL; } else { type = SEMANAGE_MODULE_PATH_HLL; } ret = semanage_module_get_path( sh, modinfo, type, path, sizeof(path)); if (ret != 0) { status = -3; goto cleanup; } ret = bzip(sh, path, data, data_len); if (ret <= 0) { ERR(sh, "Error while writing to %s.", path); status = -3; goto cleanup; } /* if this is an HLL, delete the CIL cache if it exists so it will get recompiled */ if (type == SEMANAGE_MODULE_PATH_HLL) { ret = semanage_module_get_path( sh, modinfo, SEMANAGE_MODULE_PATH_CIL, path, sizeof(path)); if (ret != 0) { status = -3; goto cleanup; } if (stat(path, &sb) == 0) { ret = unlink(path); if (ret != 0) { ERR(sh, "Error while removing cached CIL file %s: %s", path, strerror(errno)); status = -3; goto cleanup; } } } cleanup: semanage_module_key_destroy(sh, &higher_key); semanage_module_info_destroy(sh, higher_info); free(higher_info); umask(mask); return status; } static int semanage_direct_remove_key(semanage_handle_t *sh, const semanage_module_key_t *modkey) { assert(sh); assert(modkey); int status = 0; int ret = 0; char path[PATH_MAX]; semanage_module_info_t *modinfo = NULL; semanage_module_key_t modkey_tmp; ret = semanage_module_key_init(sh, &modkey_tmp); if (ret != 0) { status = -1; goto cleanup; } /* validate module key */ ret = semanage_module_validate_priority(modkey->priority); if (ret != 0) { errno = 0; ERR(sh, "Priority %d is invalid.", modkey->priority); status = -1; goto cleanup; } ret = semanage_module_validate_name(modkey->name); if (ret != 0) { errno = 0; ERR(sh, "Name %s is invalid.", modkey->name); status = -1; goto cleanup; } ret = semanage_module_key_set_name(sh, &modkey_tmp, modkey->name); if (ret != 0) { status = -1; goto cleanup; } /* get module path */ ret = semanage_module_get_path( sh, (const semanage_module_info_t *)modkey, SEMANAGE_MODULE_PATH_NAME, path, sizeof(path)); if (ret != 0) { status = -2; goto cleanup; } /* remove directory */ ret = semanage_remove_directory(path); if (ret != 0) { ERR(sh, "Unable to remove module %s at priority %d.", modkey->name, modkey->priority); status = -2; goto cleanup; } /* check if its the last module at any priority */ ret = semanage_module_get_module_info(sh, &modkey_tmp, &modinfo); if (ret != 0) { /* info that no other module will override */ errno = 0; INFO(sh, "Removing last %s module (no other %s module exists at another priority).", modkey->name, modkey->name); /* remove disabled status file */ ret = semanage_module_get_path( sh, (const semanage_module_info_t *)modkey, SEMANAGE_MODULE_PATH_DISABLED, path, sizeof(path)); if (ret != 0) { status = -1; goto cleanup; } struct stat sb; if (stat(path, &sb) == 0) { ret = unlink(path); if (ret != 0) { status = -1; goto cleanup; } } } else { /* if a lower priority module is going to become active */ if (modkey->priority > modinfo->priority) { /* inform what the new active module will be */ errno = 0; INFO(sh, "%s module at priority %d is now active.", modinfo->name, modinfo->priority); } } cleanup: semanage_module_key_destroy(sh, &modkey_tmp); semanage_module_info_destroy(sh, modinfo); free(modinfo); return status; } libsemanage/src/direct_api.h0100644 0000000 0000000 00000002662 13756670064 015143 0ustar000000000 0000000 /* Authors: Jason Tang * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_DIRECT_API_H_ #define _SEMANAGE_DIRECT_API_H_ /* Circular dependency */ struct semanage_handle; /* Direct component of handle */ struct semanage_direct_handle { /* Locking */ int activelock_file_fd; int translock_file_fd; }; int semanage_direct_connect(struct semanage_handle *sh); int semanage_direct_is_managed(struct semanage_handle *sh); int semanage_direct_access_check(struct semanage_handle *sh); int semanage_direct_mls_enabled(struct semanage_handle *sh); #include #include ssize_t bunzip(struct semanage_handle *sh, FILE *f, char **data); #endif libsemanage/src/dso.h0100644 0000000 0000000 00000001212 13756670064 013613 0ustar000000000 0000000 #ifndef _SEMANAGE_DSO_H #define _SEMANAGE_DSO_H 1 #ifdef SHARED # define hidden __attribute__ ((visibility ("hidden"))) # define hidden_proto(fct) __hidden_proto (fct, fct##_internal) # define __hidden_proto(fct, internal) \ extern __typeof (fct) internal; \ extern __typeof (fct) fct __asm (#internal) hidden; # if defined(__alpha__) || defined(__mips__) # define hidden_def(fct) \ asm (".globl " #fct "\n" #fct " = " #fct "_internal"); # else # define hidden_def(fct) \ asm (".globl " #fct "\n.set " #fct ", " #fct "_internal"); #endif #else # define hidden # define hidden_proto(fct) # define hidden_def(fct) #endif #endif libsemanage/src/exception.sh0100644 0000000 0000000 00000000734 13756670064 015217 0ustar000000000 0000000 function except() { echo " %exception $1 { \$action if (result < 0) { PyErr_SetFromErrno(PyExc_OSError); SWIG_fail; } } " } if ! ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/semanage/semanage.h then # clang does not support -aux-info so fall back to gcc gcc -x c -c -I../include - -aux-info temp.aux < ../include/semanage/semanage.h fi for i in `awk '/extern int/ { print $6 }' temp.aux`; do except $i ; done rm -f -- temp.aux -.o libsemanage/src/fcontext_internal.h0100644 0000000 0000000 00000002654 13756670064 016567 0ustar000000000 0000000 #ifndef _SEMANAGE_FCONTEXT_INTERNAL_H_ #define _SEMANAGE_FCONTEXT_INTERNAL_H_ #include #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_fcontext_key_create) hidden_proto(semanage_fcontext_key_extract) hidden_proto(semanage_fcontext_key_free) hidden_proto(semanage_fcontext_compare) hidden_proto(semanage_fcontext_compare2) hidden_proto(semanage_fcontext_create) hidden_proto(semanage_fcontext_get_expr) hidden_proto(semanage_fcontext_set_expr) hidden_proto(semanage_fcontext_get_type) hidden_proto(semanage_fcontext_get_type_str) hidden_proto(semanage_fcontext_set_type) hidden_proto(semanage_fcontext_get_con) hidden_proto(semanage_fcontext_set_con) hidden_proto(semanage_fcontext_clone) hidden_proto(semanage_fcontext_free) hidden_proto(semanage_fcontext_iterate_local) /* FCONTEXT RECORD: metod table */ extern record_table_t SEMANAGE_FCONTEXT_RTABLE; extern int fcontext_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void fcontext_file_dbase_release(dbase_config_t * dconfig); extern int hidden semanage_fcontext_validate_local(semanage_handle_t * handle, const sepol_policydb_t * policydb); #endif libsemanage/src/fcontext_record.c0100644 0000000 0000000 00000015130 13756670064 016215 0ustar000000000 0000000 struct semanage_fcontext; struct semanage_fcontext_key; typedef struct semanage_fcontext record_t; typedef struct semanage_fcontext_key record_key_t; #define DBASE_RECORD_DEFINED #include #include #include "fcontext_internal.h" #include "context_internal.h" #include "debug.h" struct semanage_fcontext { /* Matching expression */ char *expr; /* Type of object */ int type; /* Context */ semanage_context_t *con; }; struct semanage_fcontext_key { /* Matching expression */ char *expr; /* Type of object */ int type; }; /* Key */ int semanage_fcontext_key_create(semanage_handle_t * handle, const char *expr, int type, semanage_fcontext_key_t ** key_ptr) { semanage_fcontext_key_t *tmp_key = (semanage_fcontext_key_t *) malloc(sizeof(semanage_fcontext_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not " "create file context key"); return STATUS_ERR; } tmp_key->expr = strdup(expr); if (!tmp_key->expr) { ERR(handle, "out of memory, could not create file context key."); free(tmp_key); return STATUS_ERR; } tmp_key->type = type; *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(semanage_fcontext_key_create) int semanage_fcontext_key_extract(semanage_handle_t * handle, const semanage_fcontext_t * fcontext, semanage_fcontext_key_t ** key_ptr) { if (semanage_fcontext_key_create(handle, fcontext->expr, fcontext->type, key_ptr) < 0) { ERR(handle, "could not extract key from " "file context %s (%s)", fcontext->expr, semanage_fcontext_get_type_str(fcontext->type)); return STATUS_ERR; } return STATUS_SUCCESS; } hidden_def(semanage_fcontext_key_extract) void semanage_fcontext_key_free(semanage_fcontext_key_t * key) { free(key->expr); free(key); } hidden_def(semanage_fcontext_key_free) int semanage_fcontext_compare(const semanage_fcontext_t * fcontext, const semanage_fcontext_key_t * key) { int rv = strcmp(fcontext->expr, key->expr); if (rv != 0) return rv; else { if (fcontext->type < key->type) return -1; else if (key->type < fcontext->type) return 1; else return 0; } } hidden_def(semanage_fcontext_compare) int semanage_fcontext_compare2(const semanage_fcontext_t * fcontext, const semanage_fcontext_t * fcontext2) { int rv = strcmp(fcontext->expr, fcontext2->expr); if (rv != 0) return rv; else { if (fcontext->type < fcontext2->type) return -1; else if (fcontext2->type < fcontext->type) return 1; else return 0; } } hidden_def(semanage_fcontext_compare2) static int semanage_fcontext_compare2_qsort(const semanage_fcontext_t ** fcontext, const semanage_fcontext_t ** fcontext2) { return semanage_fcontext_compare2(*fcontext, *fcontext2); } /* Create */ int semanage_fcontext_create(semanage_handle_t * handle, semanage_fcontext_t ** fcontext) { semanage_fcontext_t *tmp_fcontext = (semanage_fcontext_t *) malloc(sizeof(semanage_fcontext_t)); if (!tmp_fcontext) { ERR(handle, "out of memory, could not create " "file context record"); return STATUS_ERR; } tmp_fcontext->expr = NULL; tmp_fcontext->type = SEMANAGE_FCONTEXT_ALL; tmp_fcontext->con = NULL; *fcontext = tmp_fcontext; return STATUS_SUCCESS; } hidden_def(semanage_fcontext_create) /* Regexp */ const char *semanage_fcontext_get_expr(const semanage_fcontext_t * fcontext) { return fcontext->expr; } hidden_def(semanage_fcontext_get_expr) int semanage_fcontext_set_expr(semanage_handle_t * handle, semanage_fcontext_t * fcontext, const char *expr) { char *tmp_expr = strdup(expr); if (!tmp_expr) { ERR(handle, "out of memory, " "could not set regexp string"); return STATUS_ERR; } free(fcontext->expr); fcontext->expr = tmp_expr; return STATUS_SUCCESS; } hidden_def(semanage_fcontext_set_expr) /* Type */ int semanage_fcontext_get_type(const semanage_fcontext_t * fcontext) { return fcontext->type; } hidden_def(semanage_fcontext_get_type) const char *semanage_fcontext_get_type_str(int type) { switch (type) { case SEMANAGE_FCONTEXT_ALL: return "all files"; case SEMANAGE_FCONTEXT_REG: return "regular file"; case SEMANAGE_FCONTEXT_DIR: return "directory"; case SEMANAGE_FCONTEXT_CHAR: return "character device"; case SEMANAGE_FCONTEXT_BLOCK: return "block device"; case SEMANAGE_FCONTEXT_SOCK: return "socket"; case SEMANAGE_FCONTEXT_LINK: return "symbolic link"; case SEMANAGE_FCONTEXT_PIPE: return "named pipe"; default: return "????"; } } hidden_def(semanage_fcontext_get_type_str) void semanage_fcontext_set_type(semanage_fcontext_t * fcontext, int type) { fcontext->type = type; } hidden_def(semanage_fcontext_set_type) /* Context */ semanage_context_t *semanage_fcontext_get_con(const semanage_fcontext_t * fcontext) { return fcontext->con; } hidden_def(semanage_fcontext_get_con) int semanage_fcontext_set_con(semanage_handle_t * handle, semanage_fcontext_t * fcontext, semanage_context_t * con) { semanage_context_t *newcon; if (semanage_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set file context"); return STATUS_ERR; } semanage_context_free(fcontext->con); fcontext->con = newcon; return STATUS_SUCCESS; } hidden_def(semanage_fcontext_set_con) /* Deep copy clone */ int semanage_fcontext_clone(semanage_handle_t * handle, const semanage_fcontext_t * fcontext, semanage_fcontext_t ** fcontext_ptr) { semanage_fcontext_t *new_fcontext = NULL; if (semanage_fcontext_create(handle, &new_fcontext) < 0) goto err; if (semanage_fcontext_set_expr(handle, new_fcontext, fcontext->expr) < 0) goto err; new_fcontext->type = fcontext->type; if (fcontext->con && (semanage_context_clone(handle, fcontext->con, &new_fcontext->con) < 0)) goto err; *fcontext_ptr = new_fcontext; return STATUS_SUCCESS; err: ERR(handle, "could not clone file context record"); semanage_fcontext_free(new_fcontext); return STATUS_ERR; } hidden_def(semanage_fcontext_clone) /* Destroy */ void semanage_fcontext_free(semanage_fcontext_t * fcontext) { if (!fcontext) return; free(fcontext->expr); semanage_context_free(fcontext->con); free(fcontext); } hidden_def(semanage_fcontext_free) /* Record base functions */ record_table_t SEMANAGE_FCONTEXT_RTABLE = { .create = semanage_fcontext_create, .key_extract = semanage_fcontext_key_extract, .key_free = semanage_fcontext_key_free, .clone = semanage_fcontext_clone, .compare = semanage_fcontext_compare, .compare2 = semanage_fcontext_compare2, .compare2_qsort = semanage_fcontext_compare2_qsort, .free = semanage_fcontext_free, }; libsemanage/src/fcontexts_file.c0100644 0000000 0000000 00000010746 13756670064 016051 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_fcontext; struct semanage_fcontext_key; typedef struct semanage_fcontext record_t; typedef struct semanage_fcontext_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include "fcontext_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static const char *type_str(int type) { switch (type) { default: case SEMANAGE_FCONTEXT_ALL: return " "; case SEMANAGE_FCONTEXT_REG: return "--"; case SEMANAGE_FCONTEXT_DIR: return "-d"; case SEMANAGE_FCONTEXT_CHAR: return "-c"; case SEMANAGE_FCONTEXT_BLOCK: return "-b"; case SEMANAGE_FCONTEXT_SOCK: return "-s"; case SEMANAGE_FCONTEXT_LINK: return "-l"; case SEMANAGE_FCONTEXT_PIPE: return "-p"; } } static int fcontext_print(semanage_handle_t * handle, semanage_fcontext_t * fcontext, FILE * str) { char *con_str = NULL; const char *expr = semanage_fcontext_get_expr(fcontext); int type = semanage_fcontext_get_type(fcontext); const char *print_str = type_str(type); const char *tstr = semanage_fcontext_get_type_str(type); semanage_context_t *con = semanage_fcontext_get_con(fcontext); if (fprintf(str, "%s %s ", expr, print_str) < 0) goto err; if (con != NULL) { if (semanage_context_to_string(handle, con, &con_str) < 0) goto err; if (fprintf(str, "%s\n", con_str) < 0) goto err; free(con_str); con_str = NULL; } else { if (fprintf(str, "<>\n") < 0) goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not print file context for " "%s (%s) to stream", expr, tstr); free(con_str); return STATUS_ERR; } static int fcontext_parse(semanage_handle_t * handle, parse_info_t * info, semanage_fcontext_t * fcontext) { char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Regexp */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_fcontext_set_expr(handle, fcontext, str) < 0) goto err; free(str); str = NULL; /* Type */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (!strcasecmp(str, "-s")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_SOCK); else if (!strcasecmp(str, "-p")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_PIPE); else if (!strcasecmp(str, "-b")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_BLOCK); else if (!strcasecmp(str, "-l")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_LINK); else if (!strcasecmp(str, "-c")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_CHAR); else if (!strcasecmp(str, "-d")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_DIR); else if (!strcasecmp(str, "--")) semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_REG); else goto process_context; free(str); str = NULL; /* Context */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; process_context: if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (con && semanage_fcontext_set_con(handle, fcontext, con) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_context_free(con); return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse file context record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* FCONTEXT RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_FCONTEXT_FILE_RTABLE = { .parse = fcontext_parse, .print = fcontext_print, }; int fcontext_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_FCONTEXT_RTABLE, &SEMANAGE_FCONTEXT_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void fcontext_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/fcontexts_local.c0100644 0000000 0000000 00000006723 13756670064 016224 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_fcontext; struct semanage_fcontext_key; typedef struct semanage_fcontext_key record_key_t; typedef struct semanage_fcontext record_t; #define DBASE_RECORD_DEFINED #include #include #include #include "fcontext_internal.h" #include "context_internal.h" #include "debug.h" #include "handle.h" #include "database.h" int semanage_fcontext_modify_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, const semanage_fcontext_t * data) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_fcontext_del_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_fcontext_query_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, semanage_fcontext_t ** response) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_fcontext_exists_local(semanage_handle_t * handle, const semanage_fcontext_key_t * key, int *response) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_fcontext_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_fcontext_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_fcontext_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } hidden_def(semanage_fcontext_iterate_local) int semanage_fcontext_list_local(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } struct validate_handler_arg { semanage_handle_t *handle; const sepol_policydb_t *policydb; }; static int validate_handler(const semanage_fcontext_t * fcon, void *varg) { char *str; /* Unpack varg */ struct validate_handler_arg *arg = (struct validate_handler_arg *)varg; semanage_handle_t *handle = arg->handle; const sepol_policydb_t *policydb = arg->policydb; /* Unpack fcontext */ const char *expr = semanage_fcontext_get_expr(fcon); int type = semanage_fcontext_get_type(fcon); const char *type_str = semanage_fcontext_get_type_str(type); semanage_context_t *con = semanage_fcontext_get_con(fcon); if (con && sepol_context_check(handle->sepolh, policydb, (sepol_context_t *) con) < 0) goto invalid; return 0; invalid: if (semanage_context_to_string(handle, con, &str) >= 0) { ERR(handle, "invalid context %s specified for %s [%s]", str, expr, type_str); free(str); } else ERR(handle, "invalid context specified for %s [%s]", expr, type_str); return -1; } int hidden semanage_fcontext_validate_local(semanage_handle_t * handle, const sepol_policydb_t * policydb) { struct validate_handler_arg arg; arg.handle = handle; arg.policydb = policydb; return semanage_fcontext_iterate_local(handle, validate_handler, &arg); } libsemanage/src/fcontexts_policy.c0100644 0000000 0000000 00000003413 13756670064 016422 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_fcontext; struct semanage_fcontext_key; typedef struct semanage_fcontext_key record_key_t; typedef struct semanage_fcontext record_t; #define DBASE_RECORD_DEFINED #include "fcontext_internal.h" #include "handle.h" #include "database.h" int semanage_fcontext_query(semanage_handle_t * handle, const semanage_fcontext_key_t * key, semanage_fcontext_t ** response) { dbase_config_t *dconfig = semanage_fcontext_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_fcontext_exists(semanage_handle_t * handle, const semanage_fcontext_key_t * key, int *response) { dbase_config_t *dconfig = semanage_fcontext_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_fcontext_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_fcontext_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_fcontext_iterate(semanage_handle_t * handle, int (*handler) (const semanage_fcontext_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_fcontext_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_fcontext_list(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_fcontext_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } int semanage_fcontext_list_homedirs(semanage_handle_t * handle, semanage_fcontext_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_fcontext_dbase_homedirs(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/genhomedircon.c0100644 0000000 0000000 00000101475 13756670064 015656 0ustar000000000 0000000 /* Author: Mark Goldman * Paul Rosenfeld * Todd C. Miller * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the * License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "semanage_store.h" #include "seuser_internal.h" #include "debug.h" #include "utilities.h" #include "genhomedircon.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* paths used in get_home_dirs() */ #define PATH_ETC_USERADD "/etc/default/useradd" #define PATH_ETC_LIBUSER "/etc/libuser.conf" #define PATH_DEFAULT_HOME "/home" #define PATH_EXPORT_HOME "/export/home" #define PATH_ETC_LOGIN_DEFS "/etc/login.defs" /* other paths */ #define PATH_SHELLS_FILE "/etc/shells" #define PATH_NOLOGIN_SHELL "/sbin/nologin" /* comments written to context file */ #define COMMENT_FILE_CONTEXT_HEADER "#\n#\n# " \ "User-specific file contexts, generated via libsemanage\n" \ "# use semanage command to manage system users to change" \ " the file_context\n#\n#\n" #define COMMENT_USER_HOME_CONTEXT "\n\n#\n# Home Context for user %s" \ "\n#\n\n" /* placeholders used in the template file which are searched for and replaced */ #define TEMPLATE_HOME_ROOT "HOME_ROOT" #define TEMPLATE_HOME_DIR "HOME_DIR" /* these are legacy */ #define TEMPLATE_USER "USER" #define TEMPLATE_ROLE "ROLE" /* new names */ #define TEMPLATE_USERNAME "%{USERNAME}" #define TEMPLATE_USERID "%{USERID}" #define FALLBACK_SENAME "user_u" #define FALLBACK_PREFIX "user" #define FALLBACK_LEVEL "s0" #define FALLBACK_NAME "[^/]+" #define FALLBACK_UIDGID "[0-9]+" #define DEFAULT_LOGIN "__default__" #define CONTEXT_NONE "<>" typedef struct user_entry { char *name; char *uid; char *gid; char *sename; char *prefix; char *home; char *level; char *login; char *homedir_role; struct user_entry *next; } genhomedircon_user_entry_t; typedef struct { const char *fcfilepath; int usepasswd; const char *homedir_template_path; genhomedircon_user_entry_t *fallback; semanage_handle_t *h_semanage; sepol_policydb_t *policydb; } genhomedircon_settings_t; typedef struct { const char *search_for; const char *replace_with; } replacement_pair_t; typedef struct { const char *dir; int matched; } fc_match_handle_t; typedef struct IgnoreDir { struct IgnoreDir *next; char *dir; } ignoredir_t; ignoredir_t *ignore_head = NULL; static void ignore_free(void) { ignoredir_t *next; while (ignore_head) { next = ignore_head->next; free(ignore_head->dir); free(ignore_head); ignore_head = next; } } static int ignore_setup(char *ignoredirs) { char *tok; ignoredir_t *ptr = NULL; tok = strtok(ignoredirs, ";"); while(tok) { ptr = calloc(sizeof(ignoredir_t),1); if (!ptr) goto err; ptr->dir = strdup(tok); if (!ptr->dir) goto err; ptr->next = ignore_head; ignore_head = ptr; tok = strtok(NULL, ";"); } return 0; err: free(ptr); ignore_free(); return -1; } static int ignore(const char *homedir) { ignoredir_t *ptr = ignore_head; while (ptr) { if (strcmp(ptr->dir, homedir) == 0) { return 1; } ptr = ptr->next; } return 0; } static int prefix_is_homedir_role(const semanage_user_t *user, const char *prefix) { return strcmp(OBJECT_R, prefix) == 0 || semanage_user_has_role(user, prefix); } static semanage_list_t *default_shell_list(void) { semanage_list_t *list = NULL; if (semanage_list_push(&list, "/bin/csh") || semanage_list_push(&list, "/bin/tcsh") || semanage_list_push(&list, "/bin/ksh") || semanage_list_push(&list, "/bin/bsh") || semanage_list_push(&list, "/bin/ash") || semanage_list_push(&list, "/usr/bin/ksh") || semanage_list_push(&list, "/usr/bin/pdksh") || semanage_list_push(&list, "/bin/zsh") || semanage_list_push(&list, "/bin/sh") || semanage_list_push(&list, "/bin/bash")) goto fail; return list; fail: semanage_list_destroy(&list); return NULL; } static semanage_list_t *get_shell_list(void) { FILE *shells; char *temp = NULL; semanage_list_t *list = NULL; size_t buff_len = 0; ssize_t len; shells = fopen(PATH_SHELLS_FILE, "r"); if (!shells) return default_shell_list(); while ((len = getline(&temp, &buff_len, shells)) > 0) { if (temp[len-1] == '\n') temp[len-1] = 0; if (strcmp(temp, PATH_NOLOGIN_SHELL)) { if (semanage_list_push(&list, temp)) { free(temp); semanage_list_destroy(&list); return default_shell_list(); } } } free(temp); return list; } /* Helper function called via semanage_fcontext_iterate() */ static int fcontext_matches(const semanage_fcontext_t *fcontext, void *varg) { const char *oexpr = semanage_fcontext_get_expr(fcontext); fc_match_handle_t *handp = varg; char *expr = NULL; regex_t re; int type, retval = -1; size_t len; /* Only match ALL or DIR */ type = semanage_fcontext_get_type(fcontext); if (type != SEMANAGE_FCONTEXT_ALL && type != SEMANAGE_FCONTEXT_DIR) return 0; len = strlen(oexpr); /* Define a macro to strip a literal string from the end of oexpr */ #define rstrip_oexpr_len(cstr, cstrlen) \ do { \ if (len >= (cstrlen) && !strncmp(oexpr + len - (cstrlen), (cstr), (cstrlen))) \ len -= (cstrlen); \ } while (0) #define rstrip_oexpr(cstr) rstrip_oexpr_len(cstr, sizeof(cstr) - 1) rstrip_oexpr(".+"); rstrip_oexpr(".*"); rstrip_oexpr("(/.*)?"); rstrip_oexpr("/"); #undef rstrip_oexpr_len #undef rstrip_oexpr /* Anchor oexpr at the beginning and append pattern to eat up trailing slashes */ if (asprintf(&expr, "^%.*s/*$", (int)len, oexpr) < 0) return -1; /* Check dir against expr */ if (regcomp(&re, expr, REG_EXTENDED) != 0) goto done; if (regexec(&re, handp->dir, 0, NULL, 0) == 0) handp->matched = 1; regfree(&re); retval = 0; done: free(expr); return retval; } static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) { semanage_list_t *homedir_list = NULL; semanage_list_t *shells = NULL; fc_match_handle_t hand; char *path = NULL; uid_t temp, minuid = 500, maxuid = 60000; int minuid_set = 0; struct passwd *pwbuf; struct stat buf; path = semanage_findval(PATH_ETC_USERADD, "HOME", "="); if (path && *path) { if (semanage_list_push(&homedir_list, path)) goto fail; } free(path); path = semanage_findval(PATH_ETC_LIBUSER, "LU_HOMEDIRECTORY", "="); if (path && *path) { if (semanage_list_push(&homedir_list, path)) goto fail; } free(path); path = NULL; if (!homedir_list) { if (semanage_list_push(&homedir_list, PATH_DEFAULT_HOME)) { goto fail; } } if (!stat(PATH_EXPORT_HOME, &buf)) { if (S_ISDIR(buf.st_mode)) { if (semanage_list_push(&homedir_list, PATH_EXPORT_HOME)) { goto fail; } } } if (!(s->usepasswd)) return homedir_list; shells = get_shell_list(); assert(shells); path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL); if (path && *path) { temp = atoi(path); minuid = temp; minuid_set = 1; } free(path); path = NULL; path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL); if (path && *path) { temp = atoi(path); maxuid = temp; } free(path); path = NULL; path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "="); if (path && *path) { temp = atoi(path); if (!minuid_set || temp < minuid) { minuid = temp; minuid_set = 1; } } free(path); path = NULL; errno = 0; setpwent(); while (1) { errno = 0; pwbuf = getpwent(); if (pwbuf == NULL) break; if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid) continue; if (!semanage_list_find(shells, pwbuf->pw_shell)) continue; int len = strlen(pwbuf->pw_dir) -1; for(; len > 0 && pwbuf->pw_dir[len] == '/'; len--) { pwbuf->pw_dir[len] = '\0'; } if (strcmp(pwbuf->pw_dir, "/") == 0) continue; if (ignore(pwbuf->pw_dir)) continue; if (semanage_str_count(pwbuf->pw_dir, '/') <= 1) continue; if (!(path = strdup(pwbuf->pw_dir))) { break; } semanage_rtrim(path, '/'); if (!semanage_list_find(homedir_list, path)) { /* * Now check for an existing file context that matches * so we don't label a non-homedir as a homedir. */ hand.dir = path; hand.matched = 0; if (semanage_fcontext_iterate(s->h_semanage, fcontext_matches, &hand) == STATUS_ERR) goto fail; /* NOTE: old genhomedircon printed a warning on match */ if (hand.matched) { WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or greater than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid, maxuid); } else { if (semanage_list_push(&homedir_list, path)) goto fail; } } free(path); path = NULL; } if (errno) { WARN(s->h_semanage, "Error while fetching users. " "Returning list so far."); } if (semanage_list_sort(&homedir_list)) goto fail; endpwent(); semanage_list_destroy(&shells); return homedir_list; fail: endpwent(); free(path); semanage_list_destroy(&homedir_list); semanage_list_destroy(&shells); return NULL; } /** * @param out the FILE to put all the output in. * @return 0 on success */ static int write_file_context_header(FILE * out) { if (fprintf(out, COMMENT_FILE_CONTEXT_HEADER) < 0) { return STATUS_ERR; } return STATUS_SUCCESS; } /* Predicates for use with semanage_slurp_file_filter() the homedir_template * file currently contains lines that serve as the template for a user's * homedir. * * It also contains lines that are the template for the parent of a * user's home directory. * * Currently, the only lines that apply to the the root of a user's home * directory are all prefixed with the string "HOME_ROOT". All other * lines apply to a user's home directory. If this changes the * following predicates need to change to reflect that. */ static int HOME_ROOT_PRED(const char *string) { return semanage_is_prefix(string, TEMPLATE_HOME_ROOT); } static int HOME_DIR_PRED(const char *string) { return semanage_is_prefix(string, TEMPLATE_HOME_DIR); } /* new names */ static int USERNAME_CONTEXT_PRED(const char *string) { return (int)( (strstr(string, TEMPLATE_USERNAME) != NULL) || (strstr(string, TEMPLATE_USERID) != NULL) ); } /* This will never match USER if USERNAME or USERID are found. */ static int USER_CONTEXT_PRED(const char *string) { if (USERNAME_CONTEXT_PRED(string)) return 0; return (int)(strstr(string, TEMPLATE_USER) != NULL); } static int STR_COMPARATOR(const void *a, const void *b) { return strcmp((const char *) a, (const char *) b); } /* make_tempate * @param s the settings holding the paths to various files * @param pred function pointer to function to use as filter for slurp * file filter * @return a list of lines from the template file with inappropriate * lines filtered out. */ static semanage_list_t *make_template(genhomedircon_settings_t * s, int (*pred) (const char *)) { FILE *template_file = NULL; semanage_list_t *template_data = NULL; template_file = fopen(s->homedir_template_path, "r"); if (!template_file) return NULL; template_data = semanage_slurp_file_filter(template_file, pred); fclose(template_file); return template_data; } static char *replace_all(const char *str, const replacement_pair_t * repl) { char *retval, *retval2; int i; if (!str || !repl) return NULL; retval = strdup(str); for (i = 0; retval != NULL && repl[i].search_for; i++) { retval2 = semanage_str_replace(repl[i].search_for, repl[i].replace_with, retval, 0); free(retval); retval = retval2; } return retval; } static const char *extract_context(const char *line) { const char *p = line; size_t off; off = strlen(p); p += off; /* consider trailing whitespaces */ while (off > 0) { p--; off--; if (!isspace(*p)) break; } if (off == 0) return NULL; /* find the last field in line */ while (off > 0 && !isspace(*(p - 1))) { p--; off--; } return p; } static int check_line(genhomedircon_settings_t * s, const char *line) { sepol_context_t *ctx_record = NULL; const char *ctx_str; int result; ctx_str = extract_context(line); if (!ctx_str) return STATUS_ERR; result = sepol_context_from_string(s->h_semanage->sepolh, ctx_str, &ctx_record); if (result == STATUS_SUCCESS && ctx_record != NULL) { result = sepol_context_check(s->h_semanage->sepolh, s->policydb, ctx_record); sepol_context_free(ctx_record); } return result; } static int write_replacements(genhomedircon_settings_t * s, FILE * out, const semanage_list_t * tpl, const replacement_pair_t *repl) { char *line; for (; tpl; tpl = tpl->next) { line = replace_all(tpl->data, repl); if (!line) goto fail; if (check_line(s, line) == STATUS_SUCCESS) { if (fprintf(out, "%s\n", line) < 0) goto fail; } free(line); } return STATUS_SUCCESS; fail: free(line); return STATUS_ERR; } static int write_contexts(genhomedircon_settings_t *s, FILE *out, semanage_list_t *tpl, const replacement_pair_t *repl, const genhomedircon_user_entry_t *user) { char *line, *temp; sepol_context_t *context; char *new_context_str; for (; tpl; tpl = tpl->next) { context = NULL; new_context_str = NULL; line = replace_all(tpl->data, repl); if (!line) { goto fail; } const char *old_context_str = extract_context(line); if (!old_context_str) { goto fail; } if (strcmp(old_context_str, CONTEXT_NONE) == 0) { if (check_line(s, line) == STATUS_SUCCESS && fprintf(out, "%s\n", line) < 0) { goto fail; } free(line); continue; } sepol_handle_t *sepolh = s->h_semanage->sepolh; if (sepol_context_from_string(sepolh, old_context_str, &context) < 0) { goto fail; } if (sepol_context_set_user(sepolh, context, user->sename) < 0) { goto fail; } if (sepol_policydb_mls_enabled(s->policydb) && sepol_context_set_mls(sepolh, context, user->level) < 0) { goto fail; } if (user->homedir_role && sepol_context_set_role(sepolh, context, user->homedir_role) < 0) { goto fail; } if (sepol_context_to_string(sepolh, context, &new_context_str) < 0) { goto fail; } temp = semanage_str_replace(old_context_str, new_context_str, line, 1); if (!temp) { goto fail; } free(line); line = temp; if (check_line(s, line) == STATUS_SUCCESS) { if (fprintf(out, "%s\n", line) < 0) goto fail; } free(line); sepol_context_free(context); free(new_context_str); } return STATUS_SUCCESS; fail: free(line); sepol_context_free(context); free(new_context_str); return STATUS_ERR; } static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out, semanage_list_t * tpl, const genhomedircon_user_entry_t *user) { replacement_pair_t repl[] = { {.search_for = TEMPLATE_HOME_DIR,.replace_with = user->home}, {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, {NULL, NULL} }; if (strcmp(user->name, FALLBACK_NAME) == 0) { if (fprintf(out, COMMENT_USER_HOME_CONTEXT, FALLBACK_SENAME) < 0) return STATUS_ERR; } else { if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user->name) < 0) return STATUS_ERR; } return write_contexts(s, out, tpl, repl, user); } static int write_home_root_context(genhomedircon_settings_t * s, FILE * out, semanage_list_t * tpl, char *homedir) { replacement_pair_t repl[] = { {.search_for = TEMPLATE_HOME_ROOT,.replace_with = homedir}, {NULL, NULL} }; return write_replacements(s, out, tpl, repl); } static int write_username_context(genhomedircon_settings_t * s, FILE * out, semanage_list_t * tpl, const genhomedircon_user_entry_t *user) { replacement_pair_t repl[] = { {.search_for = TEMPLATE_USERNAME,.replace_with = user->name}, {.search_for = TEMPLATE_USERID,.replace_with = user->uid}, {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, {NULL, NULL} }; return write_contexts(s, out, tpl, repl, user); } static int write_user_context(genhomedircon_settings_t * s, FILE * out, semanage_list_t * tpl, const genhomedircon_user_entry_t *user) { replacement_pair_t repl[] = { {.search_for = TEMPLATE_USER,.replace_with = user->name}, {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, {NULL, NULL} }; return write_contexts(s, out, tpl, repl, user); } static int seuser_sort_func(const void *arg1, const void *arg2) { const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1; const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;; const char *name1 = semanage_seuser_get_name(*u1); const char *name2 = semanage_seuser_get_name(*u2); if (name1[0] == '%' && name2[0] == '%') { return 0; } else if (name1[0] == '%') { return 1; } else if (name2[0] == '%') { return -1; } return strcmp(name1, name2); } static int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2) { return strcmp(semanage_user_get_name(*arg1), semanage_user_get_name(*arg2)); } static int name_user_cmp(char *key, semanage_user_t ** val) { return strcmp(key, semanage_user_get_name(*val)); } static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, const char *u, const char *g, const char *sen, const char *pre, const char *h, const char *l, const char *ln, const char *hd_role) { genhomedircon_user_entry_t *temp = NULL; char *name = NULL; char *uid = NULL; char *gid = NULL; char *sename = NULL; char *prefix = NULL; char *home = NULL; char *level = NULL; char *lname = NULL; char *homedir_role = NULL; temp = malloc(sizeof(genhomedircon_user_entry_t)); if (!temp) goto cleanup; name = strdup(n); if (!name) goto cleanup; uid = strdup(u); if (!uid) goto cleanup; gid = strdup(g); if (!gid) goto cleanup; sename = strdup(sen); if (!sename) goto cleanup; prefix = strdup(pre); if (!prefix) goto cleanup; home = strdup(h); if (!home) goto cleanup; level = strdup(l); if (!level) goto cleanup; lname = strdup(ln); if (!lname) goto cleanup; if (hd_role) { homedir_role = strdup(hd_role); if (!homedir_role) goto cleanup; } temp->name = name; temp->uid = uid; temp->gid = gid; temp->sename = sename; temp->prefix = prefix; temp->home = home; temp->level = level; temp->login = lname; temp->homedir_role = homedir_role; temp->next = (*list); (*list) = temp; return STATUS_SUCCESS; cleanup: free(name); free(uid); free(gid); free(sename); free(prefix); free(home); free(level); free(lname); free(homedir_role); free(temp); return STATUS_ERR; } static void pop_user_entry(genhomedircon_user_entry_t ** list) { genhomedircon_user_entry_t *temp; if (!list || !(*list)) return; temp = *list; *list = temp->next; free(temp->name); free(temp->uid); free(temp->gid); free(temp->sename); free(temp->prefix); free(temp->home); free(temp->level); free(temp->login); free(temp->homedir_role); free(temp); } static int setup_fallback_user(genhomedircon_settings_t * s) { semanage_seuser_t **seuser_list = NULL; unsigned int nseusers = 0; semanage_user_key_t *key = NULL; semanage_user_t *u = NULL; const char *name = NULL; const char *seuname = NULL; const char *prefix = NULL; const char *level = NULL; const char *homedir_role = NULL; unsigned int i; int retval; int errors = 0; retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers); if (retval < 0 || (nseusers < 1)) { /* if there are no users, this function can't do any other work */ return errors; } for (i = 0; i < nseusers; i++) { name = semanage_seuser_get_name(seuser_list[i]); if (strcmp(name, DEFAULT_LOGIN) == 0) { seuname = semanage_seuser_get_sename(seuser_list[i]); /* find the user structure given the name */ if (semanage_user_key_create(s->h_semanage, seuname, &key) < 0) { errors = STATUS_ERR; break; } if (semanage_user_query(s->h_semanage, key, &u) < 0) { prefix = name; level = FALLBACK_LEVEL; } else { prefix = semanage_user_get_prefix(u); level = semanage_user_get_mlslevel(u); if (!level) level = FALLBACK_LEVEL; } if (prefix_is_homedir_role(u, prefix)) { homedir_role = prefix; } if (push_user_entry(&(s->fallback), FALLBACK_NAME, FALLBACK_UIDGID, FALLBACK_UIDGID, seuname, prefix, "", level, FALLBACK_NAME, homedir_role) != 0) errors = STATUS_ERR; semanage_user_key_free(key); if (u) semanage_user_free(u); break; } } for (i = 0; i < nseusers; i++) semanage_seuser_free(seuser_list[i]); free(seuser_list); return errors; } static genhomedircon_user_entry_t *find_user(genhomedircon_user_entry_t *head, const char *name) { for(; head; head = head->next) { if (strcmp(head->name, name) == 0) { return head; } } return NULL; } static int add_user(genhomedircon_settings_t * s, genhomedircon_user_entry_t **head, semanage_user_t *user, const char *name, const char *sename, const char *selogin) { if (selogin[0] == '%') { genhomedircon_user_entry_t *orig = find_user(*head, name); if (orig != NULL && orig->login[0] == '%') { ERR(s->h_semanage, "User %s is already mapped to" " group %s, but also belongs to group %s. Add an" " explicit mapping for this user to" " override group mappings.", name, orig->login + 1, selogin + 1); return STATUS_ERR; } else if (orig != NULL) { // user mappings take precedence return STATUS_SUCCESS; } } int retval = STATUS_ERR; char *rbuf = NULL; long rbuflen; struct passwd pwstorage, *pwent = NULL; const char *prefix = NULL; const char *level = NULL; const char *homedir_role = NULL; char uid[11]; char gid[11]; errno = 0; /* Allocate space for the getpwnam_r buffer */ rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (rbuflen == -1 && errno == 0) /* sysconf returning -1 with no errno means indeterminate size */ rbuflen = 1024; else if (rbuflen <= 0) goto cleanup; rbuf = malloc(rbuflen); if (rbuf == NULL) goto cleanup; if (user) { prefix = semanage_user_get_prefix(user); level = semanage_user_get_mlslevel(user); if (!level) { level = FALLBACK_LEVEL; } } else { prefix = name; level = FALLBACK_LEVEL; } if (prefix_is_homedir_role(user, prefix)) { homedir_role = prefix; } retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); if (retval != 0 || pwent == NULL) { if (retval != 0 && retval != ENOENT) { goto cleanup; } WARN(s->h_semanage, "user %s not in password file", name); retval = STATUS_SUCCESS; goto cleanup; } int len = strlen(pwent->pw_dir) -1; for(; len > 0 && pwent->pw_dir[len] == '/'; len--) { pwent->pw_dir[len] = '\0'; } if (strcmp(pwent->pw_dir, "/") == 0) { /* don't relabel / genhomdircon checked to see if root * was the user and if so, set his home directory to * /root */ retval = STATUS_SUCCESS; goto cleanup; } if (ignore(pwent->pw_dir)) { retval = STATUS_SUCCESS; goto cleanup; } len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid); if (len < 0 || len >= (int)sizeof(uid)) { goto cleanup; } len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid); if (len < 0 || len >= (int)sizeof(gid)) { goto cleanup; } retval = push_user_entry(head, name, uid, gid, sename, prefix, pwent->pw_dir, level, selogin, homedir_role); cleanup: free(rbuf); return retval; } static int get_group_users(genhomedircon_settings_t * s, genhomedircon_user_entry_t **head, semanage_user_t *user, const char *sename, const char *selogin) { int retval = STATUS_ERR; unsigned int i; long grbuflen; char *grbuf = NULL; struct group grstorage, *group = NULL; struct passwd *pw = NULL; errno = 0; grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (grbuflen == -1 && errno == 0) /* sysconf returning -1 with no errno means indeterminate size */ grbuflen = 1024; else if (grbuflen <= 0) goto cleanup; grbuf = malloc(grbuflen); if (grbuf == NULL) goto cleanup; const char *grname = selogin + 1; errno = 0; while ( (retval = getgrnam_r(grname, &grstorage, grbuf, (size_t) grbuflen, &group)) != 0 && errno == ERANGE ) { char *new_grbuf; grbuflen *= 2; if (grbuflen < 0) /* the member list could exceed 2Gb on a system with a 32-bit CPU (where * sizeof(long) = 4) - if this ever happened, the loop would become infinite. */ goto cleanup; new_grbuf = realloc(grbuf, grbuflen); if (new_grbuf == NULL) goto cleanup; grbuf = new_grbuf; } if (retval != 0) goto cleanup; if (group == NULL) { ERR(s->h_semanage, "Can't find group named %s\n", grname); goto cleanup; } size_t nmembers = 0; char **members = group->gr_mem; while (*members != NULL) { nmembers++; members++; } for (i = 0; i < nmembers; i++) { const char *uname = group->gr_mem[i]; if (add_user(s, head, user, uname, sename, selogin) < 0) { goto cleanup; } } setpwent(); while (1) { errno = 0; pw = getpwent(); if (pw == NULL) break; // skip users who also have this group as their // primary group if (lfind(pw->pw_name, group->gr_mem, &nmembers, sizeof(char *), &STR_COMPARATOR)) { continue; } if (group->gr_gid == pw->pw_gid) { if (add_user(s, head, user, pw->pw_name, sename, selogin) < 0) { goto cleanup; } } } retval = STATUS_SUCCESS; cleanup: endpwent(); free(grbuf); return retval; } static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, int *errors) { genhomedircon_user_entry_t *head = NULL; semanage_seuser_t **seuser_list = NULL; unsigned int nseusers = 0; semanage_user_t **user_list = NULL; unsigned int nusers = 0; semanage_user_t **u = NULL; const char *name = NULL; const char *seuname = NULL; unsigned int i; int retval; *errors = 0; retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers); if (retval < 0 || (nseusers < 1)) { /* if there are no users, this function can't do any other work */ return NULL; } if (semanage_user_list(s->h_semanage, &user_list, &nusers) < 0) { nusers = 0; } qsort(seuser_list, nseusers, sizeof(semanage_seuser_t *), &seuser_sort_func); qsort(user_list, nusers, sizeof(semanage_user_t *), (int (*)(const void *, const void *))&user_sort_func); for (i = 0; i < nseusers; i++) { seuname = semanage_seuser_get_sename(seuser_list[i]); name = semanage_seuser_get_name(seuser_list[i]); if (strcmp(name, DEFAULT_LOGIN) == 0) continue; /* find the user structure given the name */ u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *), (int (*)(const void *, const void *)) &name_user_cmp); /* %groupname syntax */ if (name[0] == '%') { retval = get_group_users(s, &head, *u, seuname, name); } else { retval = add_user(s, &head, *u, name, seuname, name); } if (retval != 0) { *errors = STATUS_ERR; goto cleanup; } } cleanup: if (*errors) { for (; head; pop_user_entry(&head)) { /* the pop function takes care of all the cleanup so the loop body is just empty */ } } for (i = 0; i < nseusers; i++) { semanage_seuser_free(seuser_list[i]); } free(seuser_list); for (i = 0; i < nusers; i++) { semanage_user_free(user_list[i]); } free(user_list); return head; } static int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out, semanage_list_t * username_context_tpl, semanage_list_t * user_context_tpl, semanage_list_t * homedir_context_tpl) { genhomedircon_user_entry_t *users; int errors = 0; users = get_users(s, &errors); if (!users && errors) { return STATUS_ERR; } for (; users; pop_user_entry(&users)) { if (write_home_dir_context(s, out, homedir_context_tpl, users)) goto err; if (write_username_context(s, out, username_context_tpl, users)) goto err; if (write_user_context(s, out, user_context_tpl, users)) goto err; } return STATUS_SUCCESS; err: for (; users; pop_user_entry(&users)) { /* the pop function takes care of all the cleanup * so the loop body is just empty */ } return STATUS_ERR; } /** * @param s settings structure, stores various paths etc. Must never be NULL * @param out the FILE to put all the output in. * @return 0 on success */ static int write_context_file(genhomedircon_settings_t * s, FILE * out) { semanage_list_t *homedirs = NULL; semanage_list_t *h = NULL; semanage_list_t *homedir_context_tpl = NULL; semanage_list_t *homeroot_context_tpl = NULL; semanage_list_t *username_context_tpl = NULL; semanage_list_t *user_context_tpl = NULL; int retval = STATUS_SUCCESS; homedir_context_tpl = make_template(s, &HOME_DIR_PRED); homeroot_context_tpl = make_template(s, &HOME_ROOT_PRED); username_context_tpl = make_template(s, &USERNAME_CONTEXT_PRED); user_context_tpl = make_template(s, &USER_CONTEXT_PRED); if (!homedir_context_tpl && !homeroot_context_tpl && !username_context_tpl && !user_context_tpl) goto done; if (write_file_context_header(out) != STATUS_SUCCESS) { retval = STATUS_ERR; goto done; } if (setup_fallback_user(s) != 0) { retval = STATUS_ERR; goto done; } if (homedir_context_tpl || homeroot_context_tpl) { homedirs = get_home_dirs(s); if (!homedirs) { WARN(s->h_semanage, "no home directories were available, exiting without writing"); goto done; } for (h = homedirs; h; h = h->next) { char *temp = NULL; if (asprintf(&temp, "%s/%s", h->data, FALLBACK_NAME) < 0) { retval = STATUS_ERR; goto done; } free(s->fallback->home); s->fallback->home = temp; if (write_home_dir_context(s, out, homedir_context_tpl, s->fallback) != STATUS_SUCCESS) { free(temp); s->fallback->home = NULL; retval = STATUS_ERR; goto done; } if (write_home_root_context(s, out, homeroot_context_tpl, h->data) != STATUS_SUCCESS) { free(temp); s->fallback->home = NULL; retval = STATUS_ERR; goto done; } free(temp); s->fallback->home = NULL; } } if (user_context_tpl || username_context_tpl) { if (write_username_context(s, out, username_context_tpl, s->fallback) != STATUS_SUCCESS) { retval = STATUS_ERR; goto done; } if (write_user_context(s, out, user_context_tpl, s->fallback) != STATUS_SUCCESS) { retval = STATUS_ERR; goto done; } if (write_gen_home_dir_context(s, out, username_context_tpl, user_context_tpl, homedir_context_tpl) != STATUS_SUCCESS) { retval = STATUS_ERR; } } done: /* Cleanup */ semanage_list_destroy(&homedirs); semanage_list_destroy(&username_context_tpl); semanage_list_destroy(&user_context_tpl); semanage_list_destroy(&homedir_context_tpl); semanage_list_destroy(&homeroot_context_tpl); return retval; } int semanage_genhomedircon(semanage_handle_t * sh, sepol_policydb_t * policydb, int usepasswd, char *ignoredirs) { genhomedircon_settings_t s; FILE *out = NULL; int retval = 0; assert(sh); s.homedir_template_path = semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL); s.fcfilepath = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS); s.fallback = calloc(1, sizeof(genhomedircon_user_entry_t)); if (s.fallback == NULL) { retval = STATUS_ERR; goto done; } s.fallback->name = strdup(FALLBACK_NAME); s.fallback->sename = strdup(FALLBACK_SENAME); s.fallback->prefix = strdup(FALLBACK_PREFIX); s.fallback->level = strdup(FALLBACK_LEVEL); if (s.fallback->name == NULL || s.fallback->sename == NULL || s.fallback->prefix == NULL || s.fallback->level == NULL) { retval = STATUS_ERR; goto done; } if (ignoredirs) ignore_setup(ignoredirs); s.usepasswd = usepasswd; s.h_semanage = sh; s.policydb = policydb; if (!(out = fopen(s.fcfilepath, "w"))) { /* couldn't open output file */ ERR(sh, "Could not open the file_context file for writing"); retval = STATUS_ERR; goto done; } retval = write_context_file(&s, out); done: if (out != NULL) fclose(out); while (s.fallback) pop_user_entry(&(s.fallback)); ignore_free(); return retval; } libsemanage/src/genhomedircon.h0100644 0000000 0000000 00000002071 13756670064 015653 0ustar000000000 0000000 /* Author: Mark Goldman * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_GENHOMEDIRCON_H_ #define _SEMANAGE_GENHOMEDIRCON_H_ #include "utilities.h" int semanage_genhomedircon(semanage_handle_t * sh, sepol_policydb_t * policydb, int usepasswd, char *ignoredirs); #endif libsemanage/src/handle.c0100644 0000000 0000000 00000023071 13756670064 014263 0ustar000000000 0000000 /* Author: Joshua Brindle * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file implements only the publicly-visible handle functions to libsemanage. */ #include #include #include #include #include #include #include #include #include "direct_api.h" #include "handle.h" #include "debug.h" #include "semanage_conf.h" #include "semanage_store.h" #define SEMANAGE_COMMIT_READ_WAIT 5 static char *private_semanage_root = NULL; int semanage_set_root(const char *root) { free(private_semanage_root); private_semanage_root = strdup(root); return 0; } hidden_def(semanage_set_root); const char * semanage_root(void) { if (private_semanage_root == NULL) { return ""; } return private_semanage_root; } hidden_def(semanage_root); semanage_handle_t *semanage_handle_create(void) { semanage_handle_t *sh = NULL; char *conf_name = NULL; /* Allocate handle */ if ((sh = calloc(1, sizeof(semanage_handle_t))) == NULL) goto err; if ((conf_name = semanage_conf_path()) == NULL) goto err; if ((sh->conf = semanage_conf_parse(conf_name)) == NULL) goto err; /* Link to sepol handle */ sh->sepolh = sepol_handle_create(); if (!sh->sepolh) goto err; sepol_msg_set_callback(sh->sepolh, semanage_msg_relay_handler, sh); /* Default priority is 400 */ sh->priority = 400; /* By default do not rebuild the policy on commit * If any changes are made, this flag is ignored */ sh->do_rebuild = 0; sh->commit_err = 0; /* By default always reload policy after commit if SELinux is enabled. */ sh->do_reload = (is_selinux_enabled() > 0); /* By default always check the file contexts file. */ sh->do_check_contexts = 1; /* By default do not create store */ sh->create_store = 0; /* Set timeout: some default value for now, later use config */ sh->timeout = SEMANAGE_COMMIT_READ_WAIT; /* Set callback */ sh->msg_callback = semanage_msg_default_handler; sh->msg_callback_arg = NULL; free(conf_name); return sh; err: free(conf_name); semanage_handle_destroy(sh); return NULL; } void semanage_set_rebuild(semanage_handle_t * sh, int do_rebuild) { assert(sh != NULL); sh->do_rebuild = do_rebuild; return; } void semanage_set_reload(semanage_handle_t * sh, int do_reload) { assert(sh != NULL); sh->do_reload = do_reload; return; } int semanage_get_hll_compiler_path(semanage_handle_t *sh, char *lang_ext, char **compiler_path) { assert(sh != NULL); assert(lang_ext != NULL); int i; int status = 0; int num_printed = 0; size_t len; char *compiler = NULL; char *lower_lang_ext = NULL; lower_lang_ext = strdup(lang_ext); if (lower_lang_ext == NULL) { ERR(sh, "Could not create copy of lang_ext. Out of memory.\n"); status = -1; goto cleanup; } /* Set lang_ext to lowercase in case a file with a mixed case extension was passed to libsemanage */ for (i = 0; lower_lang_ext[i] != '\0'; i++) { lower_lang_ext[i] = tolower(lower_lang_ext[i]); } len = strlen(sh->conf->compiler_directory_path) + strlen("/") + strlen(lower_lang_ext) + 1; compiler = malloc(len * sizeof(*compiler)); if (compiler == NULL) { ERR(sh, "Error allocating space for compiler path."); status = -1; goto cleanup; } num_printed = snprintf(compiler, len, "%s/%s", sh->conf->compiler_directory_path, lower_lang_ext); if (num_printed < 0 || (int)num_printed >= (int)len) { ERR(sh, "Error creating compiler path."); status = -1; goto cleanup; } *compiler_path = compiler; status = 0; cleanup: free(lower_lang_ext); if (status != 0) { free(compiler); } return status; } void semanage_set_create_store(semanage_handle_t * sh, int create_store) { assert(sh != NULL); sh->create_store = create_store; return; } int semanage_get_disable_dontaudit(semanage_handle_t * sh) { assert(sh != NULL); return sepol_get_disable_dontaudit(sh->sepolh); } void semanage_set_disable_dontaudit(semanage_handle_t * sh, int disable_dontaudit) { assert(sh != NULL); sepol_set_disable_dontaudit(sh->sepolh, disable_dontaudit); return; } int semanage_get_preserve_tunables(semanage_handle_t * sh) { assert(sh != NULL); return sepol_get_preserve_tunables(sh->sepolh); } void semanage_set_preserve_tunables(semanage_handle_t * sh, int preserve_tunables) { assert(sh != NULL); sepol_set_preserve_tunables(sh->sepolh, preserve_tunables); } int semanage_get_ignore_module_cache(semanage_handle_t *sh) { assert(sh != NULL); return sh->conf->ignore_module_cache; } void semanage_set_ignore_module_cache(semanage_handle_t *sh, int ignore_module_cache) { assert(sh != NULL); sh->conf->ignore_module_cache = ignore_module_cache; } void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts) { assert(sh != NULL); sh->do_check_contexts = do_check_contexts; return; } uint16_t semanage_get_default_priority(semanage_handle_t *sh) { assert(sh != NULL); return sh->priority; } int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority) { assert(sh != NULL); /* Verify priority */ if (semanage_module_validate_priority(priority) < 0) { ERR(sh, "Priority %d is invalid.", priority); return -1; } sh->priority = priority; return 0; } int semanage_is_connected(semanage_handle_t * sh) { assert(sh != NULL); return sh->is_connected; } void semanage_select_store(semanage_handle_t * sh, char *storename, enum semanage_connect_type storetype) { assert(sh != NULL); /* This just sets the storename to what the user requests, no verification of existance will be done until connect */ free(sh->conf->store_path); sh->conf->store_path = strdup(storename); assert(sh->conf->store_path); /* no way to return failure */ sh->conf->store_type = storetype; return; } void semanage_set_store_root(semanage_handle_t *sh, const char *store_root) { assert(sh != NULL); free(sh->conf->store_root_path); sh->conf->store_root_path = strdup(store_root); assert(sh->conf->store_root_path); /* no way to return failure */ return; } int semanage_is_managed(semanage_handle_t * sh) { assert(sh != NULL); if (sh->is_connected) { ERR(sh, "Already connected."); return -1; } switch (sh->conf->store_type) { case SEMANAGE_CON_DIRECT: return semanage_direct_is_managed(sh); default: ERR(sh, "The connection type specified within your semanage.conf file has not been implemented yet."); /* fall through */ } return -1; } int semanage_mls_enabled(semanage_handle_t * sh) { assert(sh != NULL); switch (sh->conf->store_type) { case SEMANAGE_CON_DIRECT: return semanage_direct_mls_enabled(sh); default: ERR(sh, "The connection type specified within your semanage.conf file has not been implemented yet."); /* fall through */ } return -1; } int semanage_connect(semanage_handle_t * sh) { assert(sh != NULL); switch (sh->conf->store_type) { case SEMANAGE_CON_DIRECT:{ if (semanage_direct_connect(sh) < 0) { return -1; } break; } default:{ ERR(sh, "The connection type specified within your semanage.conf file has not been implemented yet."); return -1; } } sh->is_connected = 1; return 0; } int semanage_access_check(semanage_handle_t * sh) { assert(sh != NULL); switch (sh->conf->store_type) { case SEMANAGE_CON_DIRECT: return semanage_direct_access_check(sh); default: return -1; } return -1; /* unreachable */ } hidden_def(semanage_access_check) int semanage_disconnect(semanage_handle_t * sh) { assert(sh != NULL && sh->funcs != NULL && sh->funcs->disconnect != NULL); if (!sh->is_connected) { return 0; } if (sh->funcs->disconnect(sh) < 0) { return -1; } sh->is_in_transaction = 0; sh->is_connected = 0; sh->modules_modified = 0; return 0; } void semanage_handle_destroy(semanage_handle_t * sh) { if (sh == NULL) return; if (sh->funcs != NULL && sh->funcs->destroy != NULL) sh->funcs->destroy(sh); semanage_conf_destroy(sh->conf); sepol_handle_destroy(sh->sepolh); free(sh); } hidden_def(semanage_handle_destroy) /********************* public transaction functions *********************/ int semanage_begin_transaction(semanage_handle_t * sh) { assert(sh != NULL && sh->funcs != NULL && sh->funcs->begin_trans != NULL); if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } if (sh->is_in_transaction) { return 0; } if (sh->funcs->begin_trans(sh) < 0) { return -1; } sh->is_in_transaction = 1; return 0; } hidden_def(semanage_begin_transaction) int semanage_commit(semanage_handle_t * sh) { int retval; assert(sh != NULL && sh->funcs != NULL && sh->funcs->commit != NULL); if (!sh->is_in_transaction) { ERR(sh, "Will not commit because caller does not have a transaction lock yet."); return -1; } retval = sh->funcs->commit(sh); sh->is_in_transaction = 0; sh->modules_modified = 0; return retval; } libsemanage/src/handle.h0100644 0000000 0000000 00000016313 13756670064 014271 0ustar000000000 0000000 /* Author: Joshua Brindle * Jason Tang * Ivan Gyurdiev * * Copyright (C) 2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_INTERNAL_HANDLE_H_ #define _SEMANAGE_INTERNAL_HANDLE_H_ #include #include #include "handle_internal.h" #include #include "modules.h" #include "semanage_conf.h" #include "database.h" #include "direct_api.h" #include "policy.h" struct semanage_handle { int con_id; /* Connection ID */ /* Error handling */ int msg_level; const char *msg_channel; const char *msg_fname; #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, semanage_handle_t * handle, const char *fmt, ...); void *msg_callback_arg; /* Direct vs Server specific handle */ union { struct semanage_direct_handle direct; } u; /* Libsepol handle */ sepol_handle_t *sepolh; semanage_conf_t *conf; uint16_t priority; int is_connected; int is_in_transaction; int do_reload; /* whether to reload policy after commit */ int do_rebuild; /* whether to rebuild policy if there were no changes */ int commit_err; /* set by semanage_direct_commit() if there are * any errors when building or committing the * sandbox to kernel policy at /etc/selinux */ int modules_modified; int create_store; /* whether to create the store if it does not exist * this will only have an effect on direct connections */ int do_check_contexts; /* whether to run setfiles check the file contexts file */ /* This timeout is used for transactions and waiting for lock -1 means wait indefinetely 0 means return immediately >0 means wait that many seconds */ int timeout; /* these function pointers will point to the appropriate * routine given the connection type. think of these as * simulating polymorphism for non-OO languages. */ struct semanage_policy_table *funcs; /* Object databases */ #define DBASE_COUNT 24 /* Local modifications */ #define DBASE_LOCAL_USERS_BASE 0 #define DBASE_LOCAL_USERS_EXTRA 1 #define DBASE_LOCAL_USERS 2 #define DBASE_LOCAL_PORTS 3 #define DBASE_LOCAL_INTERFACES 4 #define DBASE_LOCAL_BOOLEANS 5 #define DBASE_LOCAL_FCONTEXTS 6 #define DBASE_LOCAL_SEUSERS 7 #define DBASE_LOCAL_NODES 8 #define DBASE_LOCAL_IBPKEYS 9 #define DBASE_LOCAL_IBENDPORTS 10 /* Policy + Local modifications */ #define DBASE_POLICY_USERS_BASE 11 #define DBASE_POLICY_USERS_EXTRA 12 #define DBASE_POLICY_USERS 13 #define DBASE_POLICY_PORTS 14 #define DBASE_POLICY_INTERFACES 15 #define DBASE_POLICY_BOOLEANS 16 #define DBASE_POLICY_FCONTEXTS 17 #define DBASE_POLICY_FCONTEXTS_H 18 #define DBASE_POLICY_SEUSERS 19 #define DBASE_POLICY_NODES 20 #define DBASE_POLICY_IBPKEYS 21 #define DBASE_POLICY_IBENDPORTS 22 /* Active kernel policy */ #define DBASE_ACTIVE_BOOLEANS 23 dbase_config_t dbase[DBASE_COUNT]; }; /* === Local modifications === */ static inline dbase_config_t * semanage_user_base_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_USERS_BASE]; } static inline dbase_config_t * semanage_user_extra_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_USERS_EXTRA]; } static inline dbase_config_t * semanage_user_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_USERS]; } static inline dbase_config_t * semanage_port_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_PORTS]; } static inline dbase_config_t * semanage_ibpkey_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_IBPKEYS]; } static inline dbase_config_t * semanage_ibendport_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_IBENDPORTS]; } static inline dbase_config_t * semanage_iface_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_INTERFACES]; } static inline dbase_config_t * semanage_bool_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_BOOLEANS]; } static inline dbase_config_t * semanage_fcontext_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_FCONTEXTS]; } static inline dbase_config_t * semanage_seuser_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_SEUSERS]; } static inline dbase_config_t * semanage_node_dbase_local(semanage_handle_t * handle) { return &handle->dbase[DBASE_LOCAL_NODES]; } /* === Policy + Local modifications === */ static inline dbase_config_t * semanage_user_base_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_USERS_BASE]; } static inline dbase_config_t * semanage_user_extra_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_USERS_EXTRA]; } static inline dbase_config_t * semanage_user_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_USERS]; } static inline dbase_config_t * semanage_port_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_PORTS]; } static inline dbase_config_t * semanage_ibpkey_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_IBPKEYS]; } static inline dbase_config_t * semanage_ibendport_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_IBENDPORTS]; } static inline dbase_config_t * semanage_iface_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_INTERFACES]; } static inline dbase_config_t * semanage_bool_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_BOOLEANS]; } static inline dbase_config_t * semanage_fcontext_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_FCONTEXTS]; } static inline dbase_config_t * semanage_fcontext_dbase_homedirs(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_FCONTEXTS_H]; } static inline dbase_config_t * semanage_seuser_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_SEUSERS]; } static inline dbase_config_t * semanage_node_dbase_policy(semanage_handle_t * handle) { return &handle->dbase[DBASE_POLICY_NODES]; } /* === Active kernel policy === */ static inline dbase_config_t * semanage_bool_dbase_active(semanage_handle_t * handle) { return &handle->dbase[DBASE_ACTIVE_BOOLEANS]; } #endif libsemanage/src/handle_internal.h0100644 0000000 0000000 00000000525 13756670064 016163 0ustar000000000 0000000 #ifndef _SEMANAGE_HANDLE_INTERNAL_H_ #define _SEMANAGE_HANDLE_INTERNAL_H_ #include #include "dso.h" hidden_proto(semanage_begin_transaction) hidden_proto(semanage_handle_destroy) hidden_proto(semanage_reload_policy) hidden_proto(semanage_access_check) hidden_proto(semanage_set_root) hidden_proto(semanage_root) #endif libsemanage/src/ibendport_internal.h0100644 0000000 0000000 00000003114 13756670064 016713 0ustar000000000 0000000 #ifndef _SEMANAGE_IBENDPORT_INTERNAL_H_ #define _SEMANAGE_IBENDPORT_INTERNAL_H_ #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_ibendport_create) hidden_proto(semanage_ibendport_compare) hidden_proto(semanage_ibendport_compare2) hidden_proto(semanage_ibendport_clone) hidden_proto(semanage_ibendport_free) hidden_proto(semanage_ibendport_key_extract) hidden_proto(semanage_ibendport_key_free) hidden_proto(semanage_ibendport_get_port) hidden_proto(semanage_ibendport_set_port) hidden_proto(semanage_ibendport_get_con) hidden_proto(semanage_ibendport_set_con) hidden_proto(semanage_ibendport_list_local) hidden_proto(semanage_ibendport_get_ibdev_name) hidden_proto(semanage_ibendport_set_ibdev_name) /* IBENDPORT RECORD: method table */ extern record_table_t SEMANAGE_IBENDPORT_RTABLE; extern int ibendport_file_dbase_init(semanage_handle_t *handle, const char *path_ro, const char *path_rw, dbase_config_t *dconfig); extern void ibendport_file_dbase_release(dbase_config_t *dconfig); extern int ibendport_policydb_dbase_init(semanage_handle_t *handle, dbase_config_t *dconfig); extern void ibendport_policydb_dbase_release(dbase_config_t *dconfig); extern int hidden semanage_ibendport_validate_local(semanage_handle_t *handle); /* ==== Internal (to ibendports) API === */ hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport, const semanage_ibendport_t **ibendport2); #endif libsemanage/src/ibendport_record.c0100644 0000000 0000000 00000010344 13756670064 016353 0ustar000000000 0000000 /*Copyright (C) 2005 Red Hat, Inc. */ /*Object: semanage_ibendport_t (Infiniband Pkey) *Object: semanage_ibendport_key_t (Infiniband Pkey Key) *Implements: record_t (Database Record) *Implements: record_key_t (Database Record Key) */ #include #include typedef sepol_context_t semanage_context_t; typedef sepol_ibendport_t semanage_ibendport_t; typedef sepol_ibendport_key_t semanage_ibendport_key_t; #define _SEMANAGE_IBENDPORT_DEFINED_ #define _SEMANAGE_CONTEXT_DEFINED_ typedef semanage_ibendport_t record_t; typedef semanage_ibendport_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "ibendport_internal.h" #include "handle.h" #include "database.h" int semanage_ibendport_compare(const semanage_ibendport_t *ibendport, const semanage_ibendport_key_t *key) { return sepol_ibendport_compare(ibendport, key); } hidden_def(semanage_ibendport_compare) int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport, const semanage_ibendport_t *ibendport2) { return sepol_ibendport_compare2(ibendport, ibendport2); } hidden_def(semanage_ibendport_compare2) hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport, const semanage_ibendport_t **ibendport2) { return sepol_ibendport_compare2(*ibendport, *ibendport2); } int semanage_ibendport_key_create(semanage_handle_t *handle, const char *ibdev_name, int port, semanage_ibendport_key_t **key_ptr) { return sepol_ibendport_key_create(handle->sepolh, ibdev_name, port, key_ptr); } int semanage_ibendport_key_extract(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, semanage_ibendport_key_t **key_ptr) { return sepol_ibendport_key_extract(handle->sepolh, ibendport, key_ptr); } hidden_def(semanage_ibendport_key_extract) void semanage_ibendport_key_free(semanage_ibendport_key_t *key) { sepol_ibendport_key_free(key); } hidden_def(semanage_ibendport_key_free) int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, char **ibdev_name_ptr) { return sepol_ibendport_get_ibdev_name(handle->sepolh, ibendport, ibdev_name_ptr); } hidden_def(semanage_ibendport_get_ibdev_name) int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle, semanage_ibendport_t *ibendport, const char *ibdev_name) { return sepol_ibendport_set_ibdev_name(handle->sepolh, ibendport, ibdev_name); } hidden_def(semanage_ibendport_set_ibdev_name) int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport) { return sepol_ibendport_get_port(ibendport); } hidden_def(semanage_ibendport_get_port) void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port) { sepol_ibendport_set_port(ibendport, port); } hidden_def(semanage_ibendport_set_port) semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport) { return sepol_ibendport_get_con(ibendport); } hidden_def(semanage_ibendport_get_con) int semanage_ibendport_set_con(semanage_handle_t *handle, semanage_ibendport_t *ibendport, semanage_context_t *con) { return sepol_ibendport_set_con(handle->sepolh, ibendport, con); } hidden_def(semanage_ibendport_set_con) int semanage_ibendport_create(semanage_handle_t *handle, semanage_ibendport_t **ibendport_ptr) { return sepol_ibendport_create(handle->sepolh, ibendport_ptr); } hidden_def(semanage_ibendport_create) int semanage_ibendport_clone(semanage_handle_t *handle, const semanage_ibendport_t *ibendport, semanage_ibendport_t **ibendport_ptr) { return sepol_ibendport_clone(handle->sepolh, ibendport, ibendport_ptr); } hidden_def(semanage_ibendport_clone) void semanage_ibendport_free(semanage_ibendport_t *ibendport) { sepol_ibendport_free(ibendport); } hidden_def(semanage_ibendport_free) /*key base functions */ record_table_t SEMANAGE_IBENDPORT_RTABLE = { .create = semanage_ibendport_create, .key_extract = semanage_ibendport_key_extract, .key_free = semanage_ibendport_key_free, .clone = semanage_ibendport_clone, .compare = semanage_ibendport_compare, .compare2 = semanage_ibendport_compare2, .compare2_qsort = semanage_ibendport_compare2_qsort, .free = semanage_ibendport_free, }; libsemanage/src/ibendports_file.c0100644 0000000 0000000 00000007224 13756670064 016202 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc. */ struct semanage_ibendport; struct semanage_ibendport_key; typedef struct semanage_ibendport record_t; typedef struct semanage_ibendport_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include "ibendport_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int ibendport_print(semanage_handle_t *handle, semanage_ibendport_t *ibendport, FILE *str) { char *con_str = NULL; char *ibdev_name_str = NULL; int port = semanage_ibendport_get_port(ibendport); if (semanage_ibendport_get_ibdev_name(handle, ibendport, &ibdev_name_str) != 0) goto err; semanage_context_t *con = semanage_ibendport_get_con(ibendport); if (fprintf(str, "ibendportcon %s ", ibdev_name_str) < 0) goto err; if (fprintf(str, "%d ", port) < 0) goto err; if (semanage_context_to_string(handle, con, &con_str) < 0) goto err; if (fprintf(str, "%s\n", con_str) < 0) goto err; free(ibdev_name_str); free(con_str); return STATUS_SUCCESS; err: ERR(handle, "could not print ibendport (%s) %u to stream", ibdev_name_str, port); free(ibdev_name_str); free(con_str); return STATUS_ERR; } static int ibendport_parse(semanage_handle_t *handle, parse_info_t *info, semanage_ibendport_t *ibendport) { int port; char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Header */ if (parse_assert_str(handle, info, "ibendportcon") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* IB Device Name */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_ibendport_set_ibdev_name(handle, ibendport, str) < 0) goto err; free(str); str = NULL; /* Port */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_int(handle, info, &port, ' ') < 0) goto err; semanage_ibendport_set_port(ibendport, port); /* context */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (!con) { ERR(handle, "<> context is not valid for ibendport (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_ibendport_set_con(handle, ibendport, con) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_context_free(con); return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse ibendport record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* IBENDPORT RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_IBENDPORT_FILE_RTABLE = { .parse = ibendport_parse, .print = ibendport_print, }; int ibendport_file_dbase_init(semanage_handle_t *handle, const char *path_ro, const char *path_rw, dbase_config_t *dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_IBENDPORT_RTABLE, &SEMANAGE_IBENDPORT_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void ibendport_file_dbase_release(dbase_config_t *dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/ibendports_local.c0100644 0000000 0000000 00000007606 13756670064 016361 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc */ struct semanage_ibendport; struct semanage_ibendport_key; typedef struct semanage_ibendport_key record_key_t; typedef struct semanage_ibendport record_t; #define DBASE_RECORD_DEFINED #include #include #include #include "ibendport_internal.h" #include "debug.h" #include "handle.h" #include "database.h" int semanage_ibendport_modify_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, const semanage_ibendport_t *data) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_ibendport_del_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_ibendport_query_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, semanage_ibendport_t **response) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_ibendport_exists_local(semanage_handle_t *handle, const semanage_ibendport_key_t *key, int *response) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_ibendport_count_local(semanage_handle_t *handle, unsigned int *response) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_ibendport_iterate_local(semanage_handle_t *handle, int (*handler)(const semanage_ibendport_t *record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_ibendport_list_local(semanage_handle_t *handle, semanage_ibendport_t ***records, unsigned int *count) { dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } hidden_def(semanage_ibendport_list_local) int hidden semanage_ibendport_validate_local(semanage_handle_t *handle) { semanage_ibendport_t **ibendports = NULL; unsigned int nibendports = 0; unsigned int i = 0, j = 0; char *ibdev_name; char *ibdev_name2; int port; int port2; /* List and sort the ibendports */ if (semanage_ibendport_list_local(handle, &ibendports, &nibendports) < 0) goto err; qsort(ibendports, nibendports, sizeof(semanage_ibendport_t *), (int (*)(const void *, const void *)) &semanage_ibendport_compare2_qsort); /* Test each ibendport */ while (i < nibendports) { int stop = 0; if (STATUS_SUCCESS != semanage_ibendport_get_ibdev_name(handle, ibendports[i], &ibdev_name)) { ERR(handle, "Couldn't get IB device name"); goto err; } port = semanage_ibendport_get_port(ibendports[i]); /* Find the first ibendport with matching * ibdev_name to compare against */ do { if (j == nibendports - 1) goto next; j++; if (STATUS_SUCCESS != semanage_ibendport_get_ibdev_name(handle, ibendports[j], &ibdev_name2)) { ERR(handle, "Couldn't get IB device name."); goto err; } port2 = semanage_ibendport_get_port(ibendports[j]); stop = !strcmp(ibdev_name, ibdev_name2); } while (!stop); if (port == port2) { ERR(handle, "ibendport %s/%u already exists.", ibdev_name2, port2); goto invalid; } next: i++; j = i; } for (i = 0; i < nibendports; i++) semanage_ibendport_free(ibendports[i]); free(ibendports); return STATUS_SUCCESS; err: ERR(handle, "could not complete ibendports validity check"); invalid: for (i = 0; i < nibendports; i++) semanage_ibendport_free(ibendports[i]); free(ibendports); return STATUS_ERR; } libsemanage/src/ibendports_policy.c0100644 0000000 0000000 00000003070 13756670064 016555 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc */ struct semanage_ibendport; struct semanage_ibendport_key; typedef struct semanage_ibendport_key record_key_t; typedef struct semanage_ibendport record_t; #define DBASE_RECORD_DEFINED #include "ibendport_internal.h" #include "handle.h" #include "database.h" int semanage_ibendport_query(semanage_handle_t *handle, const semanage_ibendport_key_t *key, semanage_ibendport_t **response) { dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_ibendport_exists(semanage_handle_t *handle, const semanage_ibendport_key_t *key, int *response) { dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_ibendport_count(semanage_handle_t *handle, unsigned int *response) { dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_ibendport_iterate(semanage_handle_t *handle, int (*handler)(const semanage_ibendport_t *record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_ibendport_list(semanage_handle_t *handle, semanage_ibendport_t ***records, unsigned int *count) { dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/ibendports_policydb.c0100644 0000000 0000000 00000004015 13756670064 017063 0ustar000000000 0000000 /* * Copyright (C) 2017 Mellanox Technologies Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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. */ struct semanage_ibendport; struct semanage_ibendport_key; typedef struct semanage_ibendport record_t; typedef struct semanage_ibendport_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "ibendport_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* IBENDPORT RECORD (SEPOL): POLICYDB extension : method table */ record_policydb_table_t SEMANAGE_IBENDPORT_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t)sepol_ibendport_modify, .set = NULL, .query = (record_policydb_table_query_t)sepol_ibendport_query, .count = (record_policydb_table_count_t)sepol_ibendport_count, .exists = (record_policydb_table_exists_t)sepol_ibendport_exists, .iterate = (record_policydb_table_iterate_t)sepol_ibendport_iterate, }; int ibendport_policydb_dbase_init(semanage_handle_t *handle, dbase_config_t *dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_IBENDPORT_RTABLE, &SEMANAGE_IBENDPORT_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void ibendport_policydb_dbase_release(dbase_config_t *dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/ibpkey_internal.h0100644 0000000 0000000 00000003242 13756670064 016212 0ustar000000000 0000000 #ifndef _SEMANAGE_IBPKEY_INTERNAL_H_ #define _SEMANAGE_IBPKEY_INTERNAL_H_ #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_ibpkey_create) hidden_proto(semanage_ibpkey_compare) hidden_proto(semanage_ibpkey_compare2) hidden_proto(semanage_ibpkey_clone) hidden_proto(semanage_ibpkey_free) hidden_proto(semanage_ibpkey_key_extract) hidden_proto(semanage_ibpkey_key_free) hidden_proto(semanage_ibpkey_get_high) hidden_proto(semanage_ibpkey_get_low) hidden_proto(semanage_ibpkey_set_pkey) hidden_proto(semanage_ibpkey_set_range) hidden_proto(semanage_ibpkey_get_con) hidden_proto(semanage_ibpkey_set_con) hidden_proto(semanage_ibpkey_list_local) hidden_proto(semanage_ibpkey_get_subnet_prefix) hidden_proto(semanage_ibpkey_get_subnet_prefix_bytes) hidden_proto(semanage_ibpkey_set_subnet_prefix) hidden_proto(semanage_ibpkey_set_subnet_prefix_bytes) /* PKEY RECORD: method table */ extern record_table_t SEMANAGE_IBPKEY_RTABLE; extern int ibpkey_file_dbase_init(semanage_handle_t *handle, const char *path_ro, const char *path_rw, dbase_config_t *dconfig); extern void ibpkey_file_dbase_release(dbase_config_t *dconfig); extern int ibpkey_policydb_dbase_init(semanage_handle_t *handle, dbase_config_t *dconfig); extern void ibpkey_policydb_dbase_release(dbase_config_t *dconfig); extern int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle); /* ==== Internal (to ibpkeys) API === */ hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey, const semanage_ibpkey_t **ibpkey2); #endif libsemanage/src/ibpkey_record.c0100644 0000000 0000000 00000011247 13756670064 015653 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc. */ /* Object: semanage_ibpkey_t (Infiniband Pkey) * Object: semanage_ibpkey_key_t (Infiniband Pkey Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include #include typedef sepol_context_t semanage_context_t; typedef sepol_ibpkey_t semanage_ibpkey_t; typedef sepol_ibpkey_key_t semanage_ibpkey_key_t; #define _SEMANAGE_IBPKEY_DEFINED_ #define _SEMANAGE_CONTEXT_DEFINED_ typedef semanage_ibpkey_t record_t; typedef semanage_ibpkey_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "ibpkey_internal.h" #include "handle.h" #include "database.h" int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey, const semanage_ibpkey_key_t *key) { return sepol_ibpkey_compare(ibpkey, key); } hidden_def(semanage_ibpkey_compare) int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey, const semanage_ibpkey_t *ibpkey2) { return sepol_ibpkey_compare2(ibpkey, ibpkey2); } hidden_def(semanage_ibpkey_compare2) hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey, const semanage_ibpkey_t **ibpkey2) { return sepol_ibpkey_compare2(*ibpkey, *ibpkey2); } int semanage_ibpkey_key_create(semanage_handle_t *handle, const char *subnet_prefix, int low, int high, semanage_ibpkey_key_t **key_ptr) { return sepol_ibpkey_key_create(handle->sepolh, subnet_prefix, low, high, key_ptr); } int semanage_ibpkey_key_extract(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, semanage_ibpkey_key_t **key_ptr) { return sepol_ibpkey_key_extract(handle->sepolh, ibpkey, key_ptr); } hidden_def(semanage_ibpkey_key_extract) void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key) { sepol_ibpkey_key_free(key); } hidden_def(semanage_ibpkey_key_free) int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, char **subnet_prefix_ptr) { return sepol_ibpkey_get_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix_ptr); } hidden_def(semanage_ibpkey_get_subnet_prefix) uint64_t semanage_ibpkey_get_subnet_prefix_bytes(const semanage_ibpkey_t *ibpkey) { return sepol_ibpkey_get_subnet_prefix_bytes(ibpkey); } hidden_def(semanage_ibpkey_get_subnet_prefix_bytes) int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle, semanage_ibpkey_t *ibpkey, const char *subnet_prefix) { return sepol_ibpkey_set_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix); } hidden_def(semanage_ibpkey_set_subnet_prefix) void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey, uint64_t subnet_prefix) { return sepol_ibpkey_set_subnet_prefix_bytes(ibpkey, subnet_prefix); } hidden_def(semanage_ibpkey_set_subnet_prefix_bytes) int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey) { return sepol_ibpkey_get_low(ibpkey); } hidden_def(semanage_ibpkey_get_low) int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey) { return sepol_ibpkey_get_high(ibpkey); } hidden_def(semanage_ibpkey_get_high) void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int ibpkey_num) { sepol_ibpkey_set_pkey(ibpkey, ibpkey_num); } hidden_def(semanage_ibpkey_set_pkey) void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low, int high) { sepol_ibpkey_set_range(ibpkey, low, high); } hidden_def(semanage_ibpkey_set_range) semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t *ibpkey) { return sepol_ibpkey_get_con(ibpkey); } hidden_def(semanage_ibpkey_get_con) int semanage_ibpkey_set_con(semanage_handle_t *handle, semanage_ibpkey_t *ibpkey, semanage_context_t *con) { return sepol_ibpkey_set_con(handle->sepolh, ibpkey, con); } hidden_def(semanage_ibpkey_set_con) int semanage_ibpkey_create(semanage_handle_t *handle, semanage_ibpkey_t **ibpkey_ptr) { return sepol_ibpkey_create(handle->sepolh, ibpkey_ptr); } hidden_def(semanage_ibpkey_create) int semanage_ibpkey_clone(semanage_handle_t *handle, const semanage_ibpkey_t *ibpkey, semanage_ibpkey_t **ibpkey_ptr) { return sepol_ibpkey_clone(handle->sepolh, ibpkey, ibpkey_ptr); } hidden_def(semanage_ibpkey_clone) void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey) { sepol_ibpkey_free(ibpkey); } hidden_def(semanage_ibpkey_free) /* key base functions */ record_table_t SEMANAGE_IBPKEY_RTABLE = { .create = semanage_ibpkey_create, .key_extract = semanage_ibpkey_key_extract, .key_free = semanage_ibpkey_key_free, .clone = semanage_ibpkey_clone, .compare = semanage_ibpkey_compare, .compare2 = semanage_ibpkey_compare2, .compare2_qsort = semanage_ibpkey_compare2_qsort, .free = semanage_ibpkey_free, }; libsemanage/src/ibpkeys_file.c0100644 0000000 0000000 00000010363 13756670064 015475 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc. */ struct semanage_ibpkey; struct semanage_ibpkey_key; typedef struct semanage_ibpkey record_t; typedef struct semanage_ibpkey_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include "ibpkey_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int ibpkey_print(semanage_handle_t *handle, semanage_ibpkey_t *ibpkey, FILE *str) { char *con_str = NULL; char *subnet_prefix_str = NULL; int low = semanage_ibpkey_get_low(ibpkey); int high = semanage_ibpkey_get_high(ibpkey); if (semanage_ibpkey_get_subnet_prefix(handle, ibpkey, &subnet_prefix_str) != 0) goto err; semanage_context_t *con = semanage_ibpkey_get_con(ibpkey); if (fprintf(str, "ibpkeycon %s ", subnet_prefix_str) < 0) goto err; if (low == high) { if (fprintf(str, "%d ", low) < 0) goto err; } else { if (fprintf(str, "%d - %d ", low, high) < 0) goto err; } if (semanage_context_to_string(handle, con, &con_str) < 0) goto err; if (fprintf(str, "%s\n", con_str) < 0) goto err; free(subnet_prefix_str); free(con_str); return STATUS_SUCCESS; err: ERR(handle, "could not print ibpkey range (%s) %u - %u to stream", subnet_prefix_str, low, high); free(subnet_prefix_str); free(con_str); return STATUS_ERR; } static int ibpkey_parse(semanage_handle_t *handle, parse_info_t *info, semanage_ibpkey_t *ibpkey) { int low, high; char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Header */ if (parse_assert_str(handle, info, "ibpkeycon") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Subnet Prefix */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_ibpkey_set_subnet_prefix(handle, ibpkey, str) < 0) goto err; free(str); str = NULL; /* Range/Pkey */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_int(handle, info, &low, '-') < 0) goto err; /* If range (-) does not follow immediately, require a space * In other words, the space here is optional, but only * in the ranged case, not in the single ibpkey case, * so do a custom test */ if (*info->ptr && *info->ptr != '-') { if (parse_assert_space(handle, info) < 0) goto err; } if (parse_optional_ch(info, '-') != STATUS_NODATA) { if (parse_skip_space(handle, info) < 0) goto err; if (parse_fetch_int(handle, info, &high, ' ') < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_ibpkey_set_range(ibpkey, low, high); } else { semanage_ibpkey_set_pkey(ibpkey, low); } /* Pkey context */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (!con) { ERR(handle, "<> context is not valid for ibpkeys (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_ibpkey_set_con(handle, ibpkey, con) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_context_free(con); return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse ibpkey record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* IBPKEY RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_IBPKEY_FILE_RTABLE = { .parse = ibpkey_parse, .print = ibpkey_print, }; int ibpkey_file_dbase_init(semanage_handle_t *handle, const char *path_ro, const char *path_rw, dbase_config_t *dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_IBPKEY_RTABLE, &SEMANAGE_IBPKEY_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void ibpkey_file_dbase_release(dbase_config_t *dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/ibpkeys_local.c0100644 0000000 0000000 00000010500 13756670064 015641 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc. */ struct semanage_ibpkey; struct semanage_ibpkey_key; typedef struct semanage_ibpkey_key record_key_t; typedef struct semanage_ibpkey record_t; #define DBASE_RECORD_DEFINED #include #include #include #include "ibpkey_internal.h" #include "debug.h" #include "handle.h" #include "database.h" int semanage_ibpkey_modify_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, const semanage_ibpkey_t *data) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_ibpkey_del_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_ibpkey_query_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, semanage_ibpkey_t **response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_ibpkey_exists_local(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, int *response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_ibpkey_count_local(semanage_handle_t *handle, unsigned int *response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_ibpkey_iterate_local(semanage_handle_t *handle, int (*handler)(const semanage_ibpkey_t *record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_ibpkey_list_local(semanage_handle_t *handle, semanage_ibpkey_t ***records, unsigned int *count) { dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } hidden_def(semanage_ibpkey_list_local) int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle) { semanage_ibpkey_t **ibpkeys = NULL; unsigned int nibpkeys = 0; unsigned int i = 0, j = 0; uint64_t subnet_prefix; uint64_t subnet_prefix2; char *subnet_prefix_str; char *subnet_prefix_str2; int low, high; int low2, high2; /* List and sort the ibpkeys */ if (semanage_ibpkey_list_local(handle, &ibpkeys, &nibpkeys) < 0) goto err; qsort(ibpkeys, nibpkeys, sizeof(semanage_ibpkey_t *), (int (*)(const void *, const void *)) &semanage_ibpkey_compare2_qsort); /* Test each ibpkey for overlap */ while (i < nibpkeys) { if (STATUS_SUCCESS != semanage_ibpkey_get_subnet_prefix(handle, ibpkeys[i], &subnet_prefix_str)) { ERR(handle, "Couldn't get subnet prefix string"); goto err; } subnet_prefix = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[i]); low = semanage_ibpkey_get_low(ibpkeys[i]); high = semanage_ibpkey_get_high(ibpkeys[i]); /* Find the first ibpkey with matching * subnet_prefix to compare against */ do { if (j == nibpkeys - 1) goto next; j++; if (STATUS_SUCCESS != semanage_ibpkey_get_subnet_prefix(handle, ibpkeys[j], &subnet_prefix_str2)) { ERR(handle, "Couldn't get subnet prefix string"); goto err; } subnet_prefix2 = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[j]); low2 = semanage_ibpkey_get_low(ibpkeys[j]); high2 = semanage_ibpkey_get_high(ibpkeys[j]); } while (subnet_prefix != subnet_prefix2); /* Overlap detected */ if (low2 <= high) { ERR(handle, "ibpkey overlap between ranges " "(%s) %u - %u <--> (%s) %u - %u.", subnet_prefix_str, low, high, subnet_prefix_str2, low2, high2); goto invalid; } /* If closest ibpkey of matching subnet prefix doesn't overlap * with test ibpkey, neither do the rest of them, because that's * how the sort function works on ibpkeys - lower bound * ibpkeys come first */ next: i++; j = i; } for (i = 0; i < nibpkeys; i++) semanage_ibpkey_free(ibpkeys[i]); free(ibpkeys); return STATUS_SUCCESS; err: ERR(handle, "could not complete ibpkeys validity check"); invalid: for (i = 0; i < nibpkeys; i++) semanage_ibpkey_free(ibpkeys[i]); free(ibpkeys); return STATUS_ERR; } libsemanage/src/ibpkeys_policy.c0100644 0000000 0000000 00000002723 13756670064 016056 0ustar000000000 0000000 /* Copyright (C) 2017 Mellanox Technologies Inc. */ struct semanage_ibpkey; struct semanage_ibpkey_key; typedef struct semanage_ibpkey_key record_key_t; typedef struct semanage_ibpkey record_t; #define DBASE_RECORD_DEFINED #include "ibpkey_internal.h" #include "handle.h" #include "database.h" int semanage_ibpkey_query(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, semanage_ibpkey_t **response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_ibpkey_exists(semanage_handle_t *handle, const semanage_ibpkey_key_t *key, int *response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_ibpkey_count(semanage_handle_t *handle, unsigned int *response) { dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_ibpkey_iterate(semanage_handle_t *handle, int (*handler)(const semanage_ibpkey_t *record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_ibpkey_list(semanage_handle_t *handle, semanage_ibpkey_t ***records, unsigned int *count) { dbase_config_t *dconfig = semanage_ibpkey_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/ibpkeys_policydb.c0100644 0000000 0000000 00000003734 13756670064 016367 0ustar000000000 0000000 /* * Copyright (C) 2017 Mellanox Technologies Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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. */ struct semanage_ibpkey; struct semanage_ibpkey_key; typedef struct semanage_ibpkey record_t; typedef struct semanage_ibpkey_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "ibpkey_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* PKEY RECORD (SEPOL): POLICYDB extension : method table */ record_policydb_table_t SEMANAGE_IBPKEY_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t)sepol_ibpkey_modify, .set = NULL, .query = (record_policydb_table_query_t)sepol_ibpkey_query, .count = (record_policydb_table_count_t)sepol_ibpkey_count, .exists = (record_policydb_table_exists_t)sepol_ibpkey_exists, .iterate = (record_policydb_table_iterate_t)sepol_ibpkey_iterate, }; int ibpkey_policydb_dbase_init(semanage_handle_t *handle, dbase_config_t *dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_IBPKEY_RTABLE, &SEMANAGE_IBPKEY_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void ibpkey_policydb_dbase_release(dbase_config_t *dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/iface_internal.h0100644 0000000 0000000 00000002350 13756670064 015775 0ustar000000000 0000000 #ifndef _SEMANAGE_IFACE_INTERNAL_H_ #define _SEMANAGE_IFACE_INTERNAL_H_ #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_iface_create) hidden_proto(semanage_iface_compare) hidden_proto(semanage_iface_compare2) hidden_proto(semanage_iface_clone) hidden_proto(semanage_iface_free) hidden_proto(semanage_iface_get_ifcon) hidden_proto(semanage_iface_get_msgcon) hidden_proto(semanage_iface_get_name) hidden_proto(semanage_iface_key_extract) hidden_proto(semanage_iface_key_free) hidden_proto(semanage_iface_set_ifcon) hidden_proto(semanage_iface_set_msgcon) hidden_proto(semanage_iface_set_name) /* IFACE RECORD: metod table */ extern record_table_t SEMANAGE_IFACE_RTABLE; extern int iface_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void iface_policydb_dbase_release(dbase_config_t * dconfig); extern int iface_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void iface_file_dbase_release(dbase_config_t * dconfig); #endif libsemanage/src/iface_record.c0100644 0000000 0000000 00000007453 13756670064 015443 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_iface_t (Network Interface) * Object: semanage_iface_key_t (Network Interface Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include #include typedef sepol_context_t semanage_context_t; typedef sepol_iface_t semanage_iface_t; typedef sepol_iface_key_t semanage_iface_key_t; #define _SEMANAGE_CONTEXT_DEFINED_ #define _SEMANAGE_IFACE_DEFINED_ typedef sepol_iface_t record_t; typedef sepol_iface_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "iface_internal.h" #include "handle.h" #include "database.h" /* Key */ int semanage_iface_compare(const semanage_iface_t * iface, const semanage_iface_key_t * key) { return sepol_iface_compare(iface, key); } hidden_def(semanage_iface_compare) int semanage_iface_compare2(const semanage_iface_t * iface, const semanage_iface_t * iface2) { return sepol_iface_compare2(iface, iface2); } hidden_def(semanage_iface_compare2) static int semanage_iface_compare2_qsort(const semanage_iface_t ** iface, const semanage_iface_t ** iface2) { return sepol_iface_compare2(*iface, *iface2); } int semanage_iface_key_create(semanage_handle_t * handle, const char *name, semanage_iface_key_t ** key_ptr) { return sepol_iface_key_create(handle->sepolh, name, key_ptr); } int semanage_iface_key_extract(semanage_handle_t * handle, const semanage_iface_t * iface, semanage_iface_key_t ** key_ptr) { return sepol_iface_key_extract(handle->sepolh, iface, key_ptr); } hidden_def(semanage_iface_key_extract) void semanage_iface_key_free(semanage_iface_key_t * key) { sepol_iface_key_free(key); } hidden_def(semanage_iface_key_free) /* Name */ const char *semanage_iface_get_name(const semanage_iface_t * iface) { return sepol_iface_get_name(iface); } hidden_def(semanage_iface_get_name) int semanage_iface_set_name(semanage_handle_t * handle, semanage_iface_t * iface, const char *name) { return sepol_iface_set_name(handle->sepolh, iface, name); } hidden_def(semanage_iface_set_name) /* Context */ semanage_context_t *semanage_iface_get_ifcon(const semanage_iface_t * iface) { return sepol_iface_get_ifcon(iface); } hidden_def(semanage_iface_get_ifcon) int semanage_iface_set_ifcon(semanage_handle_t * handle, semanage_iface_t * iface, semanage_context_t * con) { return sepol_iface_set_ifcon(handle->sepolh, iface, con); } hidden_def(semanage_iface_set_ifcon) semanage_context_t *semanage_iface_get_msgcon(const semanage_iface_t * iface) { return sepol_iface_get_msgcon(iface); } hidden_def(semanage_iface_get_msgcon) int semanage_iface_set_msgcon(semanage_handle_t * handle, semanage_iface_t * iface, semanage_context_t * con) { return sepol_iface_set_msgcon(handle->sepolh, iface, con); } hidden_def(semanage_iface_set_msgcon) /* Create/Clone/Destroy */ int semanage_iface_create(semanage_handle_t * handle, semanage_iface_t ** iface_ptr) { return sepol_iface_create(handle->sepolh, iface_ptr); } hidden_def(semanage_iface_create) int semanage_iface_clone(semanage_handle_t * handle, const semanage_iface_t * iface, semanage_iface_t ** iface_ptr) { return sepol_iface_clone(handle->sepolh, iface, iface_ptr); } hidden_def(semanage_iface_clone) void semanage_iface_free(semanage_iface_t * iface) { sepol_iface_free(iface); } hidden_def(semanage_iface_free) /* Record base functions */ record_table_t SEMANAGE_IFACE_RTABLE = { .create = semanage_iface_create, .key_extract = semanage_iface_key_extract, .key_free = semanage_iface_key_free, .clone = semanage_iface_clone, .compare = semanage_iface_compare, .compare2 = semanage_iface_compare2, .compare2_qsort = semanage_iface_compare2_qsort, .free = semanage_iface_free, }; libsemanage/src/interfaces_file.c0100644 0000000 0000000 00000007760 13756670064 016161 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_iface; struct semanage_iface_key; typedef struct semanage_iface record_t; typedef struct semanage_iface_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include "iface_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int iface_print(semanage_handle_t * handle, semanage_iface_t * iface, FILE * str) { char *con_str = NULL; const char *name = semanage_iface_get_name(iface); semanage_context_t *ifcon = semanage_iface_get_ifcon(iface); semanage_context_t *msgcon = semanage_iface_get_msgcon(iface); if (fprintf(str, "netifcon %s ", name) < 0) goto err; if (semanage_context_to_string(handle, ifcon, &con_str) < 0) goto err; if (fprintf(str, "%s ", con_str) < 0) goto err; free(con_str); con_str = NULL; if (semanage_context_to_string(handle, msgcon, &con_str) < 0) goto err; if (fprintf(str, "%s\n", con_str) < 0) goto err; free(con_str); con_str = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not print interface %s to stream", name); free(con_str); return STATUS_ERR; } static int iface_parse(semanage_handle_t * handle, parse_info_t * info, semanage_iface_t * iface) { char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Header */ if (parse_assert_str(handle, info, "netifcon") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Name */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_iface_set_name(handle, iface, str) < 0) goto err; free(str); str = NULL; /* Interface context */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (con == NULL) { ERR(handle, "<> context is not valid for " "interfaces (%s: %u)\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_iface_set_ifcon(handle, iface, con) < 0) goto err; semanage_context_free(con); con = NULL; /* Message context */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (con == NULL) { ERR(handle, "<> context is not valid for " "interfaces (%s: %u)\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_iface_set_msgcon(handle, iface, con) < 0) goto err; semanage_context_free(con); con = NULL; if (parse_assert_space(handle, info) < 0) goto err; return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse interface record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* IFACE RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_IFACE_FILE_RTABLE = { .parse = iface_parse, .print = iface_print, }; int iface_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_IFACE_RTABLE, &SEMANAGE_IFACE_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void iface_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/interfaces_local.c0100644 0000000 0000000 00000003674 13756670064 016334 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_iface; struct semanage_iface_key; typedef struct semanage_iface_key record_key_t; typedef struct semanage_iface record_t; #define DBASE_RECORD_DEFINED #include "iface_internal.h" #include "handle.h" #include "database.h" int semanage_iface_modify_local(semanage_handle_t * handle, const semanage_iface_key_t * key, const semanage_iface_t * data) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_iface_del_local(semanage_handle_t * handle, const semanage_iface_key_t * key) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_iface_query_local(semanage_handle_t * handle, const semanage_iface_key_t * key, semanage_iface_t ** response) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_iface_exists_local(semanage_handle_t * handle, const semanage_iface_key_t * key, int *response) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_iface_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_iface_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_iface_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_iface_list_local(semanage_handle_t * handle, semanage_iface_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_iface_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/interfaces_policy.c0100644 0000000 0000000 00000002670 13756670064 016534 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_iface; struct semanage_iface_key; typedef struct semanage_iface_key record_key_t; typedef struct semanage_iface record_t; #define DBASE_RECORD_DEFINED #include "iface_internal.h" #include "handle.h" #include "database.h" int semanage_iface_query(semanage_handle_t * handle, const semanage_iface_key_t * key, semanage_iface_t ** response) { dbase_config_t *dconfig = semanage_iface_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_iface_exists(semanage_handle_t * handle, const semanage_iface_key_t * key, int *response) { dbase_config_t *dconfig = semanage_iface_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_iface_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_iface_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_iface_iterate(semanage_handle_t * handle, int (*handler) (const semanage_iface_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_iface_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_iface_list(semanage_handle_t * handle, semanage_iface_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_iface_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/interfaces_policydb.c0100644 0000000 0000000 00000004341 13756670064 017037 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_iface; struct semanage_iface_key; typedef struct semanage_iface record_t; typedef struct semanage_iface_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "iface_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* INTERFACE RECRORD (SEPOL): POLICYDB extension: method table */ record_policydb_table_t SEMANAGE_IFACE_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t) sepol_iface_modify, .set = NULL, .query = (record_policydb_table_query_t) sepol_iface_query, .count = (record_policydb_table_count_t) sepol_iface_count, .exists = (record_policydb_table_exists_t) sepol_iface_exists, .iterate = (record_policydb_table_iterate_t) sepol_iface_iterate, }; int iface_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_IFACE_RTABLE, &SEMANAGE_IFACE_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void iface_policydb_dbase_release(dbase_config_t * dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/libsemanage.map0100644 0000000 0000000 00000004517 13756670064 015636 0ustar000000000 0000000 LIBSEMANAGE_1.0 { global: semanage_handle_create; semanage_handle_destroy; semanage_is_managed; semanage_connect; semanage_disconnect; semanage_msg_*; semanage_begin_transaction; semanage_commit; semanage_module_install; semanage_module_install_file; semanage_module_upgrade; semanage_module_upgrade_file; semanage_module_install_base; semanage_module_install_base_file; semanage_module_enable; semanage_module_disable; semanage_module_remove; semanage_module_list; semanage_module_info_datum_destroy; semanage_module_list_nth; semanage_module_get_name; semanage_module_get_version; semanage_select_store; semanage_module_get_enabled; semanage_reload_policy; semanage_set_reload; semanage_set_rebuild; semanage_set_root; semanage_root; semanage_user_*; semanage_bool_*; semanage_seuser_*; semanage_iface_*; semanage_port_*; semanage_context_*; semanage_ibpkey_*; semanage_ibendport_*; semanage_node_*; semanage_fcontext_*; semanage_access_check; semanage_set_create_store; semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit; semanage_mls_enabled; semanage_set_check_contexts; semanage_get_preserve_tunables; semanage_set_preserve_tunables; local: *; }; LIBSEMANAGE_1.1 { global: semanage_module_install; semanage_module_extract; semanage_get_hll_compiler_path; semanage_get_ignore_module_cache; semanage_set_ignore_module_cache; semanage_get_default_priority; semanage_set_default_priority; semanage_module_info_create; semanage_module_info_destroy; semanage_module_info_get_priority; semanage_module_info_get_name; semanage_module_info_get_lang_ext; semanage_module_info_get_enabled; semanage_module_info_set_priority; semanage_module_info_set_name; semanage_module_info_set_lang_ext; semanage_module_info_set_enabled; semanage_module_key_create; semanage_module_key_destroy; semanage_module_key_get_priority; semanage_module_key_get_name; semanage_module_key_set_priority; semanage_module_key_set_name; semanage_module_get_module_info; semanage_module_list_all; semanage_module_get_enabled; semanage_module_set_enabled; semanage_module_install_info; semanage_module_upgrade_info; semanage_module_remove_key; semanage_set_store_root; } LIBSEMANAGE_1.0; libsemanage/src/libsemanage.pc.in0100644 0000000 0000000 00000000465 13756670064 016066 0ustar000000000 0000000 prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ Name: libsemanage Description: SELinux management library Version: @VERSION@ URL: http://userspace.selinuxproject.org/ Requires.private: libselinux libsepol Libs: -L${libdir} -lsemanage Libs.private: -lbz2 Cflags: -I${includedir} libsemanage/src/module_internal.h0100644 0000000 0000000 00000002111 13756670064 016206 0ustar000000000 0000000 #ifndef _SEMANAGE_MODULE_INTERNAL_H_ #define _SEMANAGE_MODULE_INTERNAL_H_ #include #include "dso.h" hidden_proto(semanage_module_get_name) hidden_proto(semanage_module_info_datum_destroy) hidden_proto(semanage_module_list_nth) hidden_proto(semanage_module_info_create) hidden_proto(semanage_module_info_destroy) hidden_proto(semanage_module_info_get_priority) hidden_proto(semanage_module_info_get_name) hidden_proto(semanage_module_info_get_lang_ext) hidden_proto(semanage_module_info_get_enabled) hidden_proto(semanage_module_info_set_priority) hidden_proto(semanage_module_info_set_name) hidden_proto(semanage_module_info_set_lang_ext) hidden_proto(semanage_module_info_set_enabled) hidden_proto(semanage_module_key_create) hidden_proto(semanage_module_key_destroy) hidden_proto(semanage_module_key_get_priority) hidden_proto(semanage_module_key_get_name) hidden_proto(semanage_module_key_set_priority) hidden_proto(semanage_module_key_set_name) hidden_proto(semanage_module_set_enabled) #endif libsemanage/src/modules.c0100644 0000000 0000000 00000061156 13756670064 014506 0ustar000000000 0000000 /* Author: Joshua Brindle * Caleb Case * * Copyright (C) 2004-2005,2009 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file implements only the publicly-visible module functions to libsemanage. */ #include "direct_api.h" #include "semanage_conf.h" #include "semanage_store.h" #include #include #include #include #include #include #include #include #include #include #include #include "handle.h" #include "modules.h" #include "debug.h" asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1"); asm(".symver semanage_module_get_enabled_1_0,semanage_module_get_enabled@LIBSEMANAGE_1.0"); asm(".symver semanage_module_install_pp,semanage_module_install@LIBSEMANAGE_1.0"); asm(".symver semanage_module_install_hll,semanage_module_install@@LIBSEMANAGE_1.1"); /* Takes a module stored in 'module_data' and parses its headers. * Sets reference variables 'module_name' to module's name and * 'version' to module's version. The caller is responsible for * free()ing 'module_name' and 'version'; they will be * set to NULL upon entering this function. Returns 0 on success, -1 * if out of memory, or -2 if data did not represent a module. */ static int parse_module_headers(semanage_handle_t * sh, char *module_data, size_t data_len, char **module_name, char **version) { struct sepol_policy_file *pf; int file_type; *version = NULL; if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); return -1; } sepol_policy_file_set_mem(pf, module_data, data_len); sepol_policy_file_set_handle(pf, sh->sepolh); if (module_data == NULL || data_len == 0 || sepol_module_package_info(pf, &file_type, module_name, version) == -1) { sepol_policy_file_free(pf); ERR(sh, "Could not parse module data."); return -2; } sepol_policy_file_free(pf); if (file_type != SEPOL_POLICY_MOD) { ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules."); return -2; } return 0; } /* This function is used to preserve ABI compatibility with * versions of semodule using LIBSEMANAGE_1.0 */ int semanage_module_install_pp(semanage_handle_t * sh, char *module_data, size_t data_len) { char *name = NULL; char *version = NULL; int status; if ((status = parse_module_headers(sh, module_data, data_len, &name, &version)) != 0) { goto cleanup; } status = semanage_module_install_hll(sh, module_data, data_len, name, "pp"); cleanup: free(name); free(version); return status; } int semanage_module_install_hll(semanage_handle_t * sh, char *module_data, size_t data_len, const char *name, const char *ext_lang) { if (sh->funcs->install == NULL) { ERR(sh, "No install function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->install(sh, module_data, data_len, name, ext_lang); } int semanage_module_install_file(semanage_handle_t * sh, const char *module_name) { if (sh->funcs->install_file == NULL) { ERR(sh, "No install function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->install_file(sh, module_name); } int semanage_module_extract(semanage_handle_t * sh, semanage_module_key_t *modkey, int extract_cil, void **mapped_data, size_t *data_len, semanage_module_info_t **modinfo) { if (sh->funcs->extract == NULL) { ERR(sh, "No get function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } return sh->funcs->extract(sh, modkey, extract_cil, mapped_data, data_len, modinfo); } /* Legacy function that remains to preserve ABI * compatibility. Please use semanage_module_install instead. */ int semanage_module_upgrade(semanage_handle_t * sh, char *module_data, size_t data_len) { return semanage_module_install_pp(sh, module_data, data_len); } /* Legacy function that remains to preserve ABI * compatibility. Please use semanage_module_install_file instead. */ int semanage_module_upgrade_file(semanage_handle_t * sh, const char *module_name) { return semanage_module_install_file(sh, module_name); } /* Legacy function that remains to preserve ABI * compatibility. Please use semanage_module_install instead. */ int semanage_module_install_base(semanage_handle_t * sh, char *module_data, size_t data_len) { return semanage_module_install_pp(sh, module_data, data_len); } /* Legacy function that remains to preserve ABI * compatibility. Please use semanage_module_install_file instead. */ int semanage_module_install_base_file(semanage_handle_t * sh, const char *module_name) { return semanage_module_install_file(sh, module_name); } int semanage_module_remove(semanage_handle_t * sh, char *module_name) { if (sh->funcs->remove == NULL) { ERR(sh, "No remove function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->remove(sh, module_name); } int semanage_module_list(semanage_handle_t * sh, semanage_module_info_t ** modinfo, int *num_modules) { if (sh->funcs->list == NULL) { ERR(sh, "No list function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } return sh->funcs->list(sh, modinfo, num_modules); } void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo) { if (modinfo != NULL) { modinfo->priority = 0; free(modinfo->name); modinfo->name = NULL; free(modinfo->lang_ext); modinfo->lang_ext = NULL; modinfo->enabled = -1; } } hidden_def(semanage_module_info_datum_destroy) semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list, int n) { return list + n; } hidden_def(semanage_module_list_nth) const char *semanage_module_get_name(semanage_module_info_t * modinfo) { return modinfo->name; } hidden_def(semanage_module_get_name) /* Legacy function that remains to preserve ABI * compatibility. */ const char *semanage_module_get_version(semanage_module_info_t * modinfo __attribute__ ((unused))) { return ""; } int semanage_module_info_create(semanage_handle_t *sh, semanage_module_info_t **modinfo) { assert(sh); assert(modinfo); *modinfo = malloc(sizeof(semanage_module_info_t)); if (*modinfo == NULL) return -1; return semanage_module_info_init(sh, *modinfo); } hidden_def(semanage_module_info_create) int semanage_module_info_destroy(semanage_handle_t *sh, semanage_module_info_t *modinfo) { assert(sh); if (!modinfo) { return 0; } free(modinfo->name); free(modinfo->lang_ext); return semanage_module_info_init(sh, modinfo); } hidden_def(semanage_module_info_destroy) int semanage_module_info_init(semanage_handle_t *sh, semanage_module_info_t *modinfo) { assert(sh); assert(modinfo); modinfo->priority = 0; modinfo->name = NULL; modinfo->lang_ext = NULL; modinfo->enabled = -1; return 0; } int semanage_module_info_clone(semanage_handle_t *sh, const semanage_module_info_t *source, semanage_module_info_t *target) { assert(sh); assert(source); assert(target); int status = 0; int ret = 0; ret = semanage_module_info_destroy(sh, target); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_priority(sh, target, source->priority); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_name(sh, target, source->name); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext); if (ret != 0) { status = -1; goto cleanup; } ret = semanage_module_info_set_enabled(sh, target, source->enabled); if (ret != 0) { status = -1; goto cleanup; } cleanup: if (status != 0) semanage_module_info_destroy(sh, target); return status; } int semanage_module_info_get_priority(semanage_handle_t *sh, semanage_module_info_t *modinfo, uint16_t *priority) { assert(sh); assert(modinfo); assert(priority); *priority = modinfo->priority; return 0; } hidden_def(semanage_module_info_get_priority) int semanage_module_info_get_name(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char **name) { assert(sh); assert(modinfo); assert(name); *name = modinfo->name; return 0; } hidden_def(semanage_module_info_get_name) int semanage_module_info_get_lang_ext(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char **lang_ext) { assert(sh); assert(modinfo); assert(lang_ext); *lang_ext = modinfo->lang_ext; return 0; } hidden_def(semanage_module_info_get_lang_ext) int semanage_module_info_get_enabled(semanage_handle_t *sh, semanage_module_info_t *modinfo, int *enabled) { assert(sh); assert(modinfo); assert(enabled); *enabled = modinfo->enabled; return 0; } hidden_def(semanage_module_info_get_enabled) int semanage_module_info_set_priority(semanage_handle_t *sh, semanage_module_info_t *modinfo, uint16_t priority) { assert(sh); assert(modinfo); /* Verify priority */ if (semanage_module_validate_priority(priority) < 0) { errno = 0; ERR(sh, "Priority %d is invalid.", priority); return -1; } modinfo->priority = priority; return 0; } hidden_def(semanage_module_info_set_priority) int semanage_module_info_set_name(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char *name) { assert(sh); assert(modinfo); assert(name); char * tmp; /* Verify name */ if (semanage_module_validate_name(name) < 0) { errno = 0; ERR(sh, "Name %s is invalid.", name); return -1; } tmp = strdup(name); if (!tmp) { ERR(sh, "No memory available for strdup"); return -1; } free(modinfo->name); modinfo->name = tmp; return 0; } hidden_def(semanage_module_info_set_name) int semanage_module_info_set_lang_ext(semanage_handle_t *sh, semanage_module_info_t *modinfo, const char *lang_ext) { assert(sh); assert(modinfo); assert(lang_ext); char * tmp; /* Verify extension */ if (semanage_module_validate_lang_ext(lang_ext) < 0) { errno = 0; ERR(sh, "Language extensions %s is invalid.", lang_ext); return -1; } tmp = strdup(lang_ext); if (!tmp) { ERR(sh, "No memory available for strdup"); return -1; } free(modinfo->lang_ext); modinfo->lang_ext = tmp; return 0; } hidden_def(semanage_module_info_set_lang_ext) int semanage_module_info_set_enabled(semanage_handle_t *sh, semanage_module_info_t *modinfo, int enabled) { assert(sh); assert(modinfo); /* Verify enabled */ if (semanage_module_validate_enabled(enabled) < 0) { errno = 0; ERR(sh, "Enabled status %d is invalid.", enabled); return -1; } modinfo->enabled = enabled; return 0; } hidden_def(semanage_module_info_set_enabled) int semanage_module_get_path(semanage_handle_t *sh, const semanage_module_info_t *modinfo, enum semanage_module_path_type type, char *path, size_t len) { assert(sh); assert(modinfo); assert(path); int status = 0; int ret = 0; const char *modules_path = NULL; const char *file = NULL; modules_path = sh->is_in_transaction ? semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES): semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES); switch (type) { case SEMANAGE_MODULE_PATH_PRIORITY: /* verify priority */ ret = semanage_module_validate_priority(modinfo->priority); if (ret < 0) { errno = 0; ERR(sh, "Priority %d is invalid.", modinfo->priority); status = ret; goto cleanup; } ret = snprintf(path, len, "%s/%03u", modules_path, modinfo->priority); if (ret < 0 || (size_t)ret >= len) { ERR(sh, "Unable to compose priority path."); status = -1; goto cleanup; } break; case SEMANAGE_MODULE_PATH_NAME: /* verify priority and name */ ret = semanage_module_validate_priority(modinfo->priority); if (ret < 0) { errno = 0; ERR(sh, "Priority %d is invalid.", modinfo->priority); status = -1; goto cleanup; } ret = semanage_module_validate_name(modinfo->name); if (ret < 0) { errno = 0; ERR(sh, "Name %s is invalid.", modinfo->name); status = -1; goto cleanup; } ret = snprintf(path, len, "%s/%03u/%s", modules_path, modinfo->priority, modinfo->name); if (ret < 0 || (size_t)ret >= len) { ERR(sh, "Unable to compose name path."); status = -1; goto cleanup; } break; case SEMANAGE_MODULE_PATH_HLL: if (file == NULL) file = "hll"; /* FALLTHRU */ case SEMANAGE_MODULE_PATH_CIL: if (file == NULL) file = "cil"; /* FALLTHRU */ case SEMANAGE_MODULE_PATH_LANG_EXT: if (file == NULL) file = "lang_ext"; /* verify priority and name */ ret = semanage_module_validate_priority(modinfo->priority); if (ret < 0) { errno = 0; ERR(sh, "Priority %d is invalid.", modinfo->priority); status = -1; goto cleanup; } ret = semanage_module_validate_name(modinfo->name); if (ret < 0) { errno = 0; ERR(sh, "Name %s is invalid.", modinfo->name); status = -1; goto cleanup; } ret = snprintf(path, len, "%s/%03u/%s/%s", modules_path, modinfo->priority, modinfo->name, file); if (ret < 0 || (size_t)ret >= len) { ERR(sh, "Unable to compose path for %s file.", file); status = -1; goto cleanup; } break; case SEMANAGE_MODULE_PATH_DISABLED: /* verify name */ ret = semanage_module_validate_name(modinfo->name); if (ret < 0) { errno = 0; ERR(sh, "Name %s is invalid.", modinfo->name); status = -1; goto cleanup; } ret = snprintf(path, len, "%s/disabled/%s", modules_path, modinfo->name); if (ret < 0 || (size_t)ret >= len) { ERR(sh, "Unable to compose disabled status path."); status = -1; goto cleanup; } break; default: ERR(sh, "Invalid module path type %d.", type); status = -1; goto cleanup; } cleanup: return status; } int semanage_module_key_create(semanage_handle_t *sh, semanage_module_key_t **modkey) { assert(sh); assert(modkey); *modkey = malloc(sizeof(semanage_module_key_t)); if (*modkey == NULL) return -1; return semanage_module_key_init(sh, *modkey); } hidden_def(semanage_module_key_create) int semanage_module_key_destroy(semanage_handle_t *sh, semanage_module_key_t *modkey) { assert(sh); if (!modkey) { return 0; } free(modkey->name); return semanage_module_key_init(sh, modkey); } hidden_def(semanage_module_key_destroy) int semanage_module_key_init(semanage_handle_t *sh, semanage_module_key_t *modkey) { assert(sh); assert(modkey); modkey->name = NULL; modkey->priority = 0; return 0; } int semanage_module_key_get_name(semanage_handle_t *sh, semanage_module_key_t *modkey, const char **name) { assert(sh); assert(modkey); assert(name); *name = modkey->name; return 0; } hidden_def(semanage_module_key_get_name) int semanage_module_key_get_priority(semanage_handle_t *sh, semanage_module_key_t *modkey, uint16_t *priority) { assert(sh); assert(modkey); assert(priority); *priority = modkey->priority; return 0; } hidden_def(semanage_module_key_get_priority) int semanage_module_key_set_name(semanage_handle_t *sh, semanage_module_key_t *modkey, const char *name) { assert(sh); assert(modkey); assert(name); int status = 0; char *tmp = NULL; if (semanage_module_validate_name(name) < 0) { errno = 0; ERR(sh, "Name %s is invalid.", name); return -1; } tmp = strdup(name); if (tmp == NULL) { ERR(sh, "No memory available for strdup"); status = -1; goto cleanup; } free(modkey->name); modkey->name = tmp; cleanup: return status; } hidden_def(semanage_module_key_set_name) int semanage_module_key_set_priority(semanage_handle_t *sh, semanage_module_key_t *modkey, uint16_t priority) { assert(sh); assert(modkey); if (semanage_module_validate_priority(priority) < 0) { errno = 0; ERR(sh, "Priority %d is invalid.", priority); return -1; } modkey->priority = priority; return 0; } hidden_def(semanage_module_key_set_priority) int semanage_module_get_enabled_1_1(semanage_handle_t *sh, const semanage_module_key_t *modkey, int *enabled) { assert(sh); assert(modkey); assert(enabled); if (sh->funcs->get_enabled == NULL) { ERR(sh, "No get_enabled function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } return sh->funcs->get_enabled(sh, modkey, enabled); } int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo) { return modinfo->enabled; } int semanage_module_set_enabled(semanage_handle_t *sh, const semanage_module_key_t *modkey, int enabled) { assert(sh); assert(modkey); if (sh->funcs->set_enabled == NULL) { ERR(sh, "No set_enabled function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->set_enabled(sh, modkey, enabled); } hidden_def(semanage_module_set_enabled) /* This function exists only for ABI compatability. It has been deprecated and * should not be used. Instead, use semanage_module_set_enabled() */ int semanage_module_enable(semanage_handle_t *sh, char *module_name) { int rc = -1; semanage_module_key_t *modkey = NULL; rc = semanage_module_key_create(sh, &modkey); if (rc != 0) goto exit; rc = semanage_module_key_set_name(sh, modkey, module_name); if (rc != 0) goto exit; rc = semanage_module_set_enabled(sh, modkey, 1); if (rc != 0) goto exit; rc = 0; exit: semanage_module_key_destroy(sh, modkey); free(modkey); return rc; } /* This function exists only for ABI compatability. It has been deprecated and * should not be used. Instead, use semanage_module_set_enabled() */ int semanage_module_disable(semanage_handle_t *sh, char *module_name) { int rc = -1; semanage_module_key_t *modkey = NULL; rc = semanage_module_key_create(sh, &modkey); if (rc != 0) goto exit; rc = semanage_module_key_set_name(sh, modkey, module_name); if (rc != 0) goto exit; rc = semanage_module_set_enabled(sh, modkey, 0); if (rc != 0) goto exit; rc = 0; exit: semanage_module_key_destroy(sh, modkey); free(modkey); return rc; } /* Converts a string to a priority * * returns -1 if str is not a valid priority. * returns 0 and sets priority if str is a valid priority */ int semanage_string_to_priority(const char *str, uint16_t *priority) { unsigned long val; char *endptr = NULL; int status = -1; if (str == NULL || priority == NULL) { goto exit; } errno = 0; val = strtoul(str, &endptr, 10); if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) { goto exit; } if (semanage_module_validate_priority((uint16_t)val) < 0) { goto exit; } *priority = val; status = 0; exit: return status; } /* Validates a module info struct. * * Returns -1 if module is invalid, 0 otherwise. */ int semanage_module_info_validate(const semanage_module_info_t *modinfo) { if (semanage_module_validate_priority(modinfo->priority) != 0 || semanage_module_validate_name(modinfo->name) != 0 || semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 || semanage_module_validate_enabled(modinfo->enabled) != 0) { return -1; } return 0; } #define PRIORITY_MIN 1 #define PRIORITY_MAX 999 /* Validates priority. * * returns -1 if priority is not in the valid range, returns 0 otherwise */ int semanage_module_validate_priority(uint16_t priority) { if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) { return 0; } return -1; } /* Validates module name. * * A module name must match one of the following regular expressions * to be considered valid: * * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$ * * returns -1 if name is not valid, returns 0 otherwise */ int semanage_module_validate_name(const char * name) { int status = 0; if (name == NULL) { status = -1; goto exit; } if (!isalpha(*name)) { status = -1; goto exit; } #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') for (name++; *name; name++) { if (ISVALIDCHAR(*name)) { continue; } if (*name == '.' && name++ && ISVALIDCHAR(*name)) { continue; } status = -1; goto exit; } #undef ISVALIDCHAR exit: return status; } /* Validates module enabled status. * * Valid enabled values are 1, 0, and -1. * * returns 0 if enabled is a valid value, returns -1 otherwise. */ int semanage_module_validate_enabled(int enabled) { if (enabled == 1 || enabled == 0 || enabled == -1) { return 0; } return -1; } /* Validate extension. * * An extension must match the following regular expression to be * considered valid: * * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ * * returns 0 if ext is a valid value, returns -1 otherwise. */ int semanage_module_validate_lang_ext(const char *ext) { int status = 0; if (ext == NULL) { status = -1; goto exit; } if (!isalnum(*ext)) { status = -1; goto exit; } #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') for (ext++; *ext; ext++) { if (ISVALIDCHAR(*ext)) { continue; } status = -1; goto exit; } #undef ISVALIDCHAR exit: return status; } int semanage_module_get_module_info(semanage_handle_t *sh, const semanage_module_key_t *modkey, semanage_module_info_t **modinfo) { assert(sh); assert(modkey); assert(modinfo); if (sh->funcs->get_module_info == NULL) { ERR(sh, "No get module info function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } return sh->funcs->get_module_info(sh, modkey, modinfo); } int semanage_module_list_all(semanage_handle_t *sh, semanage_module_info_t **modinfos, int *modinfos_len) { assert(sh); assert(modinfos); assert(modinfos_len); if (sh->funcs->list_all == NULL) { ERR(sh, "No list all function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } return sh->funcs->list_all(sh, modinfos, modinfos_len); } int semanage_module_install_info(semanage_handle_t *sh, const semanage_module_info_t *modinfo, char *data, size_t data_len) { if (sh->funcs->install_info == NULL) { ERR(sh, "No install info function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->install_info(sh, modinfo, data, data_len); } int semanage_module_remove_key(semanage_handle_t *sh, const semanage_module_key_t *modkey) { if (sh->funcs->remove_key== NULL) { ERR(sh, "No remove key function defined for this connection type."); return -1; } else if (!sh->is_connected) { ERR(sh, "Not connected."); return -1; } else if (!sh->is_in_transaction) { if (semanage_begin_transaction(sh) < 0) { return -1; } } sh->modules_modified = 1; return sh->funcs->remove_key(sh, modkey); } libsemanage/src/modules.h0100644 0000000 0000000 00000007233 13756670064 014507 0ustar000000000 0000000 /* Author: Joshua Brindle * Jason Tang * Caleb Case * * Copyright (C) 2005,2009 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_INTERNAL_MODULES_H_ #define _SEMANAGE_INTERNAL_MODULES_H_ #include #include "module_internal.h" int semanage_module_install_pp(semanage_handle_t * sh, char *module_data, size_t data_len); int semanage_module_install_hll(semanage_handle_t * sh, char *module_data, size_t data_len, const char *name, const char *ext_lang); int semanage_module_upgrade(semanage_handle_t * sh, char *module_data, size_t data_len); int semanage_module_upgrade_file(semanage_handle_t * sh, const char *module_name); int semanage_module_install_base(semanage_handle_t * sh, char *module_data, size_t data_len); int semanage_module_install_base_file(semanage_handle_t * sh, const char *module_name); /* Module Info */ struct semanage_module_info { uint16_t priority; /* key, module priority */ char *name; /* key, module name */ char *lang_ext; /* module source language extension */ int enabled; /* module enabled/disabled status */ }; /* Initializes a pre-allocated module info struct. * * Returns 0 on success and -1 on error. */ int semanage_module_info_init(semanage_handle_t *sh, semanage_module_info_t *modinfo); /* Clones module info @source's members into module info @target. * * Returns 0 on success and -1 on error. */ int semanage_module_info_clone(semanage_handle_t *sh, const semanage_module_info_t *source, semanage_module_info_t *target); /* Convert a cstring to a priority. * * Returns 0 on success and -1 on error. */ int semanage_string_to_priority(const char *str, uint16_t *priority); int semanage_module_info_validate(const semanage_module_info_t *modinfo); int semanage_module_validate_priority(uint16_t priority); int semanage_module_validate_name(const char *name); int semanage_module_validate_enabled(int enabled); int semanage_module_validate_lang_ext(const char *ext); int semanage_module_validate_version(const char *version); /* Module Key */ struct semanage_module_key { uint16_t priority; /* module priority */ char *name; /* module name */ }; /* Initializes a pre-allocated module key struct. * * Returns 0 on success, and -1 on error. */ int semanage_module_key_init(semanage_handle_t *sh, semanage_module_key_t *modkey); /* Module Paths */ enum semanage_module_path_type { SEMANAGE_MODULE_PATH_PRIORITY, SEMANAGE_MODULE_PATH_NAME, SEMANAGE_MODULE_PATH_HLL, SEMANAGE_MODULE_PATH_CIL, SEMANAGE_MODULE_PATH_LANG_EXT, SEMANAGE_MODULE_PATH_DISABLED, }; /* Get the module path for the given path @type. * * Returns 0 on success and -1 on error. */ int semanage_module_get_path(semanage_handle_t *sh, const semanage_module_info_t *module, enum semanage_module_path_type type, char *path, size_t len); #endif libsemanage/src/node_internal.h0100644 0000000 0000000 00000003411 13756670064 015652 0ustar000000000 0000000 #ifndef _SEMANAGE_NODE_INTERNAL_H_ #define _SEMANAGE_NODE_INTERNAL_H_ #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_node_create) hidden_proto(semanage_node_compare) hidden_proto(semanage_node_compare2) hidden_proto(semanage_node_clone) hidden_proto(semanage_node_free) hidden_proto(semanage_node_key_extract) hidden_proto(semanage_node_key_free) hidden_proto(semanage_node_get_addr) hidden_proto(semanage_node_get_addr_bytes) hidden_proto(semanage_node_get_mask) hidden_proto(semanage_node_get_mask_bytes) hidden_proto(semanage_node_get_proto) hidden_proto(semanage_node_set_addr) hidden_proto(semanage_node_set_addr_bytes) hidden_proto(semanage_node_set_mask) hidden_proto(semanage_node_set_mask_bytes) hidden_proto(semanage_node_set_proto) hidden_proto(semanage_node_get_proto_str) hidden_proto(semanage_node_get_con) hidden_proto(semanage_node_set_con) hidden_proto(semanage_node_list_local) /* NODE RECORD: method table */ extern record_table_t SEMANAGE_NODE_RTABLE; extern int node_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void node_file_dbase_release(dbase_config_t * dconfig); extern int node_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void node_policydb_dbase_release(dbase_config_t * dconfig); extern int hidden semanage_node_validate_local(semanage_handle_t * handle); /* ==== Internal (to nodes) API === */ hidden int semanage_node_compare2_qsort(const semanage_node_t ** node, const semanage_node_t ** node2); #endif libsemanage/src/node_record.c0100644 0000000 0000000 00000012444 13756670064 015315 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_node_t (Network Port) * Object: semanage_node_key_t (Network Port Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include #include #include typedef sepol_context_t semanage_context_t; typedef sepol_node_t semanage_node_t; typedef sepol_node_key_t semanage_node_key_t; #define _SEMANAGE_NODE_DEFINED_ #define _SEMANAGE_CONTEXT_DEFINED_ typedef semanage_node_t record_t; typedef semanage_node_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "node_internal.h" #include "handle.h" #include "database.h" /* Key */ int semanage_node_compare(const semanage_node_t * node, const semanage_node_key_t * key) { return sepol_node_compare(node, key); } hidden_def(semanage_node_compare) int semanage_node_compare2(const semanage_node_t * node, const semanage_node_t * node2) { return sepol_node_compare2(node, node2); } hidden_def(semanage_node_compare2) hidden int semanage_node_compare2_qsort(const semanage_node_t ** node, const semanage_node_t ** node2) { return sepol_node_compare2(*node, *node2); } int semanage_node_key_create(semanage_handle_t * handle, const char *addr, const char *mask, int proto, semanage_node_key_t ** key_ptr) { return sepol_node_key_create(handle->sepolh, addr, mask, proto, key_ptr); } int semanage_node_key_extract(semanage_handle_t * handle, const semanage_node_t * node, semanage_node_key_t ** key_ptr) { return sepol_node_key_extract(handle->sepolh, node, key_ptr); } hidden_def(semanage_node_key_extract) void semanage_node_key_free(semanage_node_key_t * key) { sepol_node_key_free(key); } hidden_def(semanage_node_key_free) /* Address */ int semanage_node_get_addr(semanage_handle_t * handle, const semanage_node_t * node, char **addr_ptr) { return sepol_node_get_addr(handle->sepolh, node, addr_ptr); } hidden_def(semanage_node_get_addr) int semanage_node_get_addr_bytes(semanage_handle_t * handle, const semanage_node_t * node, char **addr, size_t * addr_sz) { return sepol_node_get_addr_bytes(handle->sepolh, node, addr, addr_sz); } hidden_def(semanage_node_get_addr_bytes) int semanage_node_set_addr(semanage_handle_t * handle, semanage_node_t * node, int proto, const char *addr) { return sepol_node_set_addr(handle->sepolh, node, proto, addr); } hidden_def(semanage_node_set_addr) int semanage_node_set_addr_bytes(semanage_handle_t * handle, semanage_node_t * node, const char *addr, size_t addr_sz) { return sepol_node_set_addr_bytes(handle->sepolh, node, addr, addr_sz); } hidden_def(semanage_node_set_addr_bytes) /* Netmask */ int semanage_node_get_mask(semanage_handle_t * handle, const semanage_node_t * node, char **mask_ptr) { return sepol_node_get_mask(handle->sepolh, node, mask_ptr); } hidden_def(semanage_node_get_mask) int semanage_node_get_mask_bytes(semanage_handle_t * handle, const semanage_node_t * node, char **mask, size_t * mask_sz) { return sepol_node_get_mask_bytes(handle->sepolh, node, mask, mask_sz); } hidden_def(semanage_node_get_mask_bytes) int semanage_node_set_mask(semanage_handle_t * handle, semanage_node_t * node, int proto, const char *mask) { return sepol_node_set_mask(handle->sepolh, node, proto, mask); } hidden_def(semanage_node_set_mask) int semanage_node_set_mask_bytes(semanage_handle_t * handle, semanage_node_t * node, const char *mask, size_t mask_sz) { return sepol_node_set_mask_bytes(handle->sepolh, node, mask, mask_sz); } hidden_def(semanage_node_set_mask_bytes) /* Protocol */ int semanage_node_get_proto(const semanage_node_t * node) { return sepol_node_get_proto(node); } hidden_def(semanage_node_get_proto) void semanage_node_set_proto(semanage_node_t * node, int proto) { sepol_node_set_proto(node, proto); } hidden_def(semanage_node_set_proto) const char *semanage_node_get_proto_str(int proto) { return sepol_node_get_proto_str(proto); } hidden_def(semanage_node_get_proto_str) /* Context */ semanage_context_t *semanage_node_get_con(const semanage_node_t * node) { return sepol_node_get_con(node); } hidden_def(semanage_node_get_con) int semanage_node_set_con(semanage_handle_t * handle, semanage_node_t * node, semanage_context_t * con) { return sepol_node_set_con(handle->sepolh, node, con); } hidden_def(semanage_node_set_con) /* Create/Clone/Destroy */ int semanage_node_create(semanage_handle_t * handle, semanage_node_t ** node_ptr) { return sepol_node_create(handle->sepolh, node_ptr); } hidden_def(semanage_node_create) int semanage_node_clone(semanage_handle_t * handle, const semanage_node_t * node, semanage_node_t ** node_ptr) { return sepol_node_clone(handle->sepolh, node, node_ptr); } hidden_def(semanage_node_clone) void semanage_node_free(semanage_node_t * node) { sepol_node_free(node); } hidden_def(semanage_node_free) /* Port base functions */ record_table_t SEMANAGE_NODE_RTABLE = { .create = semanage_node_create, .key_extract = semanage_node_key_extract, .key_free = semanage_node_key_free, .clone = semanage_node_clone, .compare = semanage_node_compare, .compare2 = semanage_node_compare2, .compare2_qsort = semanage_node_compare2_qsort, .free = semanage_node_free, }; libsemanage/src/nodes_file.c0100644 0000000 0000000 00000010030 13756670064 015126 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_node; struct semanage_node_key; typedef struct semanage_node record_t; typedef struct semanage_node_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include "node_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int node_print(semanage_handle_t * handle, semanage_node_t * node, FILE * str) { char *con_str = NULL; char *addr = NULL; char *mask = NULL; int proto = semanage_node_get_proto(node); const char *proto_str = semanage_node_get_proto_str(proto); semanage_context_t *con = semanage_node_get_con(node); if (semanage_node_get_addr(handle, node, &addr) < 0) goto err; if (semanage_node_get_mask(handle, node, &mask) < 0) goto err; if (semanage_context_to_string(handle, con, &con_str) < 0) goto err; if (fprintf (str, "nodecon %s %s %s %s\n", proto_str, addr, mask, con_str) < 0) goto err; free(addr); free(mask); free(con_str); return STATUS_SUCCESS; err: free(addr); free(mask); free(con_str); ERR(handle, "could not print node to stream"); return STATUS_ERR; } static int node_parse(semanage_handle_t * handle, parse_info_t * info, semanage_node_t * node) { int proto; char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Header */ if (parse_assert_str(handle, info, "nodecon") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Protocol */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (!strcasecmp(str, "ipv4")) proto = SEMANAGE_PROTO_IP4; else if (!strcasecmp(str, "ipv6")) proto = SEMANAGE_PROTO_IP6; else { ERR(handle, "invalid protocol \"%s\" (%s: %u):\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; semanage_node_set_proto(node, proto); /* Address */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_node_set_addr(handle, node, proto, str) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; free(str); str = NULL; /* Netmask */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_node_set_mask(handle, node, proto, str) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; free(str); str = NULL; /* Port context */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (con == NULL) { ERR(handle, "<> context is not valid " "for nodes (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_node_set_con(handle, node, con) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_context_free(con); return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse node record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* NODE RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_NODE_FILE_RTABLE = { .parse = node_parse, .print = node_print, }; int node_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_NODE_RTABLE, &SEMANAGE_NODE_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void node_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/nodes_local.c0100644 0000000 0000000 00000003715 13756670064 015315 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_node; struct semanage_node_key; typedef struct semanage_node_key record_key_t; typedef struct semanage_node record_t; #define DBASE_RECORD_DEFINED #include "node_internal.h" #include "handle.h" #include "database.h" int semanage_node_modify_local(semanage_handle_t * handle, const semanage_node_key_t * key, const semanage_node_t * data) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_node_del_local(semanage_handle_t * handle, const semanage_node_key_t * key) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_node_query_local(semanage_handle_t * handle, const semanage_node_key_t * key, semanage_node_t ** response) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_node_exists_local(semanage_handle_t * handle, const semanage_node_key_t * key, int *response) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_node_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_node_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_node_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_node_list_local(semanage_handle_t * handle, semanage_node_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_node_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } hidden_def(semanage_node_list_local) libsemanage/src/nodes_policy.c0100644 0000000 0000000 00000002645 13756670064 015523 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_node; struct semanage_node_key; typedef struct semanage_node_key record_key_t; typedef struct semanage_node record_t; #define DBASE_RECORD_DEFINED #include "node_internal.h" #include "handle.h" #include "database.h" int semanage_node_query(semanage_handle_t * handle, const semanage_node_key_t * key, semanage_node_t ** response) { dbase_config_t *dconfig = semanage_node_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_node_exists(semanage_handle_t * handle, const semanage_node_key_t * key, int *response) { dbase_config_t *dconfig = semanage_node_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_node_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_node_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_node_iterate(semanage_handle_t * handle, int (*handler) (const semanage_node_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_node_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_node_list(semanage_handle_t * handle, semanage_node_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_node_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/nodes_policydb.c0100644 0000000 0000000 00000004307 13756670064 016026 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_node; struct semanage_node_key; typedef struct semanage_node record_t; typedef struct semanage_node_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "node_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* NODE RECORD (SEPOL): POLICYDB extension : method table */ record_policydb_table_t SEMANAGE_NODE_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t) sepol_node_modify, .set = NULL, .query = (record_policydb_table_query_t) sepol_node_query, .count = (record_policydb_table_count_t) sepol_node_count, .exists = (record_policydb_table_exists_t) sepol_node_exists, .iterate = (record_policydb_table_iterate_t) sepol_node_iterate, }; int node_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_NODE_RTABLE, &SEMANAGE_NODE_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void node_policydb_dbase_release(dbase_config_t * dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/parse_utils.c0100644 0000000 0000000 00000013746 13756670064 015372 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #include #include #include #include #include #include #include #include "parse_utils.h" #include "debug.h" int parse_init(semanage_handle_t * handle, const char *filename, void *parse_arg, parse_info_t ** info) { parse_info_t *tmp_info = (parse_info_t *) malloc(sizeof(parse_info_t)); if (!tmp_info) { ERR(handle, "out of memory, could not allocate parse structure"); return STATUS_ERR; } tmp_info->filename = filename; tmp_info->file_stream = NULL; tmp_info->working_copy = NULL; tmp_info->orig_line = NULL; tmp_info->ptr = NULL; tmp_info->lineno = 0; tmp_info->parse_arg = parse_arg; *info = tmp_info; return STATUS_SUCCESS; } void parse_release(parse_info_t * info) { parse_close(info); parse_dispose_line(info); free(info); } int parse_open(semanage_handle_t * handle, parse_info_t * info) { info->file_stream = fopen(info->filename, "r"); if (!info->file_stream && (errno != ENOENT)) { ERR(handle, "could not open file %s: %s", info->filename, strerror(errno)); return STATUS_ERR; } if (info->file_stream) __fsetlocking(info->file_stream, FSETLOCKING_BYCALLER); return STATUS_SUCCESS; } void parse_close(parse_info_t * info) { if (info->file_stream) fclose(info->file_stream); info->file_stream = NULL; } void parse_dispose_line(parse_info_t * info) { if (info->orig_line) { free(info->orig_line); info->orig_line = NULL; } if (info->working_copy) { free(info->working_copy); info->working_copy = NULL; } info->ptr = NULL; } int parse_skip_space(semanage_handle_t * handle, parse_info_t * info) { size_t buf_len = 0; ssize_t len; int lineno = info->lineno; char *buffer = NULL; char *ptr; if (info->ptr) { while (*(info->ptr) && isspace(*(info->ptr))) info->ptr++; if (*(info->ptr)) return STATUS_SUCCESS; } parse_dispose_line(info); while (info->file_stream && ((len = getline(&buffer, &buf_len, info->file_stream)) > 0)) { lineno++; /* Eat newline, preceding whitespace */ if (buffer[len - 1] == '\n') buffer[len - 1] = '\0'; ptr = buffer; while (*ptr && isspace(*ptr)) ptr++; /* Skip comments and blank lines */ if ((*ptr) && *ptr != '#') { char *tmp = strdup(buffer); if (!tmp) goto omem; info->lineno = lineno; info->working_copy = buffer; info->orig_line = tmp; info->ptr = ptr; return STATUS_SUCCESS; } } free(buffer); buffer = NULL; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not allocate buffer"); free(buffer); return STATUS_ERR; } int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info) { if (!info->ptr) { ERR(handle, "unexpected end of file (%s: %u)", info->filename, info->lineno); return STATUS_ERR; } return STATUS_SUCCESS; } int parse_assert_space(semanage_handle_t * handle, parse_info_t * info) { if (parse_assert_noeof(handle, info) < 0) return STATUS_ERR; if (*(info->ptr) && !isspace(*(info->ptr))) { ERR(handle, "missing whitespace (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); return STATUS_ERR; } if (parse_skip_space(handle, info) < 0) return STATUS_ERR; return STATUS_SUCCESS; } int parse_assert_ch(semanage_handle_t * handle, parse_info_t * info, const char ch) { if (parse_assert_noeof(handle, info) < 0) return STATUS_ERR; if (*(info->ptr) != ch) { ERR(handle, "expected character \'%c\', but found \'%c\' " "(%s: %u):\n%s", ch, *(info->ptr), info->filename, info->lineno, info->orig_line); return STATUS_ERR; } info->ptr++; return STATUS_SUCCESS; } int parse_assert_str(semanage_handle_t * handle, parse_info_t * info, const char *assert_str) { size_t len = strlen(assert_str); if (parse_assert_noeof(handle, info) < 0) return STATUS_ERR; if (strncmp(info->ptr, assert_str, len)) { ERR(handle, "experted string \"%s\", but found \"%s\" " "(%s: %u):\n%s", assert_str, info->ptr, info->filename, info->lineno, info->orig_line); return STATUS_ERR; } info->ptr += len; return STATUS_SUCCESS; } int parse_optional_ch(parse_info_t * info, const char ch) { if (!info->ptr) return STATUS_NODATA; if (*(info->ptr) != ch) return STATUS_NODATA; info->ptr++; return STATUS_SUCCESS; } int parse_optional_str(parse_info_t * info, const char *str) { size_t len = strlen(str); if (strncmp(info->ptr, str, len)) return STATUS_NODATA; info->ptr += len; return STATUS_SUCCESS; } int parse_fetch_int(semanage_handle_t * handle, parse_info_t * info, int *num, char delim) { char *str = NULL; char *test = NULL; int value = 0; if (parse_fetch_string(handle, info, &str, delim) < 0) goto err; if (!isdigit((int)*str)) { ERR(handle, "expected a numeric value: (%s: %u)\n%s", info->filename, info->lineno, info->orig_line); goto err; } value = strtol(str, &test, 10); if (*test != '\0') { ERR(handle, "could not parse numeric value \"%s\": " "(%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } *num = value; free(str); return STATUS_SUCCESS; err: ERR(handle, "could not fetch numeric value"); free(str); return STATUS_ERR; } int parse_fetch_string(semanage_handle_t * handle, parse_info_t * info, char **str, char delim) { char *start = info->ptr; int len = 0; char *tmp_str = NULL; if (parse_assert_noeof(handle, info) < 0) goto err; while (*(info->ptr) && !isspace(*(info->ptr)) && (*(info->ptr) != delim)) { info->ptr++; len++; } if (len == 0) { ERR(handle, "expected non-empty string, but did not " "find one (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); goto err; } tmp_str = (char *)malloc(len + 1); if (!tmp_str) { ERR(handle, "out of memory"); goto err; } strncpy(tmp_str, start, len); *(tmp_str + len) = '\0'; *str = tmp_str; return STATUS_SUCCESS; err: ERR(handle, "could not fetch string value"); return STATUS_ERR; } libsemanage/src/parse_utils.h0100644 0000000 0000000 00000005327 13756670064 015373 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #ifndef _SEMANAGE_PARSE_UTILS_INTERNAL_H_ #define _SEMANAGE_PARSE_UTILS_INTERNAL_H_ #include #include typedef struct parse_info { unsigned int lineno; /* Current line number */ char *orig_line; /* Original copy of the line being parsed */ char *working_copy; /* Working copy of the line being parsed */ char *ptr; /* Current parsing location */ const char *filename; /* Input stream file name */ FILE *file_stream; /* Input stream handle */ void *parse_arg; /* Caller supplied argument */ } parse_info_t; /* Initialize structure */ extern int parse_init(semanage_handle_t * handle, const char *filename, void *parse_arg, parse_info_t ** info); /* Release structure */ extern void parse_release(parse_info_t * info); /* Open file */ extern int parse_open(semanage_handle_t * handle, parse_info_t * info); /* Close file */ extern void parse_close(parse_info_t * info); /* Release resources for current line */ extern void parse_dispose_line(parse_info_t * info); /* Skip all whitespace and comments */ extern int parse_skip_space(semanage_handle_t * handle, parse_info_t * info); /* Throw an error if we're at the EOF */ extern int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info); /* Throw an error if no whitespace follows, * otherwise eat the whitespace */ extern int parse_assert_space(semanage_handle_t * handle, parse_info_t * info); /* Throw an error if the specified character * does not follow, otherwise eat that character */ extern int parse_assert_ch(semanage_handle_t * handle, parse_info_t * info, const char ch); /* Throw an error if the specified string * does not follow is not found, otherwise * eat the string */ extern int parse_assert_str(semanage_handle_t * handle, parse_info_t * info, const char *assert_str); /* Eat the optional character, if found, * or return STATUS_NODATA */ extern int parse_optional_ch(parse_info_t * info, const char ch); /* Eat the optional string, if found, * or return STATUS_NODATA */ extern int parse_optional_str(parse_info_t * info, const char *str); /* Extract the next integer, and move * the read pointer past it. Stop if * the optional character delim is encountered, * or if whitespace/eof is encountered */ int parse_fetch_int(semanage_handle_t * hgandle, parse_info_t * info, int *num, char delim); /* Extract the next string (delimited by * whitespace), and move the read pointer past it. * Stop of the optional character delim is encountered, * or if whitespace/eof is encountered. Fail if the * string is of length 0. */ extern int parse_fetch_string(semanage_handle_t * handle, parse_info_t * info, char **str_ptr, char delim); #endif libsemanage/src/policy.h0100644 0000000 0000000 00000006230 13756670064 014332 0ustar000000000 0000000 /* Author: Joshua Brindle * Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * Copyright (C) 2005 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEMANAGE_POLICY_INTERNAL_H_ #define _SEMANAGE_POLICY_INTERNAL_H_ #include "modules.h" /* Circular dependency */ struct semanage_handle; /* Backend dependent portion */ struct semanage_policy_table { /* Returns the current policy serial/commit number * A negative number is returned in case of failre */ int (*get_serial) (struct semanage_handle *); /* Destroy a connection */ void (*destroy) (struct semanage_handle *); /* Disconnect from policy */ int (*disconnect) (struct semanage_handle *); /* Begin a policy transaction */ int (*begin_trans) (struct semanage_handle *); /* Commit a policy transaction */ int (*commit) (struct semanage_handle *); /* Install a policy module */ int (*install) (struct semanage_handle *, char *, size_t, const char *, const char *); /* Install a policy module */ int (*install_file) (struct semanage_handle *, const char *); /* Extract a policy module */ int (*extract) (struct semanage_handle *, semanage_module_key_t *, int extract_cil, void **, size_t *, semanage_module_info_t **); /* Remove a policy module */ int (*remove) (struct semanage_handle *, char *); /* List policy modules */ int (*list) (struct semanage_handle *, semanage_module_info_t **, int *); /* Get module enabled status */ int (*get_enabled) (struct semanage_handle *sh, const semanage_module_key_t *key, int *enabled); /* Set module enabled status */ int (*set_enabled) (struct semanage_handle *sh, const semanage_module_key_t *key, int enabled); /* Get a module info */ int (*get_module_info) (struct semanage_handle *, const semanage_module_key_t *, semanage_module_info_t **); /* List all policy modules */ int (*list_all) (struct semanage_handle *, semanage_module_info_t **, int *); /* Install via module info */ int (*install_info) (struct semanage_handle *, const semanage_module_info_t *, char *, size_t); /* Remove via module key */ int (*remove_key) (struct semanage_handle *, const semanage_module_key_t *); }; /* Should be backend independent */ extern int semanage_base_merge_components(struct semanage_handle *handle); extern int semanage_commit_components(struct semanage_handle *handle); #endif libsemanage/src/policy_components.c0100644 0000000 0000000 00000013647 13756670064 016604 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ #include #include "policy.h" #include "handle.h" #include "database.h" #include "modules.h" #include "debug.h" /* Powers of two only */ #define MODE_SET 1 #define MODE_MODIFY 2 #define MODE_SORT 4 static int clear_obsolete(semanage_handle_t * handle, record_t ** records, unsigned int nrecords, dbase_config_t * src, dbase_config_t * dst) { record_key_t *key = NULL; unsigned int i; dbase_table_t *src_dtable = src->dtable; dbase_table_t *dst_dtable = dst->dtable; record_table_t *rtable = src_dtable->get_rtable(src->dbase); for (i = 0; i < nrecords; i++) { int exists; if (rtable->key_extract(handle, records[i], &key) < 0) goto err; if (dst_dtable->exists(handle, dst->dbase, key, &exists) < 0) goto err; if (!exists) { if (src_dtable->del(handle, src->dbase, key) < 0) goto err; rtable->free(records[i]); records[i] = NULL; /* FIXME: notice to user */ /* INFO(handle, "boolean %s is obsolete, unsetting configured value..."); */ } rtable->key_free(key); } return STATUS_SUCCESS; err: /* FIXME: handle error */ rtable->key_free(key); return STATUS_ERR; } static int load_records(semanage_handle_t * handle, dbase_config_t * dst, record_t ** records, unsigned int nrecords, int mode) { unsigned int i; record_key_t *rkey = NULL; dbase_t *dbase = dst->dbase; dbase_table_t *dtable = dst->dtable; record_table_t *rtable = dtable->get_rtable(dbase); for (i = 0; i < nrecords; i++) { /* Possibly obsoleted */ if (!records[i]) continue; if (rtable->key_extract(handle, records[i], &rkey) < 0) goto err; if (mode & MODE_SET && dtable->set(handle, dbase, rkey, records[i]) < 0) goto err; else if (mode & MODE_MODIFY && dtable->modify(handle, dbase, rkey, records[i]) < 0) goto err; rtable->key_free(rkey); } return STATUS_SUCCESS; err: /* FIXME: handle error */ rtable->key_free(rkey); return STATUS_ERR; } typedef struct load_table { dbase_config_t *src; dbase_config_t *dst; int mode; } load_table_t; /* This function must be called AFTER all modules are loaded. * Modules could be represented as a database, in which case * they should be loaded at the beginning of this function */ int semanage_base_merge_components(semanage_handle_t * handle) { unsigned int i, j; int rc = STATUS_SUCCESS; /* Order is important here - change things carefully. * System components first, local next. Verify runs with * mutual dependencies are ran after everything is merged */ load_table_t components[] = { {semanage_user_base_dbase_local(handle), semanage_user_base_dbase_policy(handle), MODE_MODIFY}, {semanage_user_extra_dbase_local(handle), semanage_user_extra_dbase_policy(handle), MODE_MODIFY}, {semanage_port_dbase_local(handle), semanage_port_dbase_policy(handle), MODE_MODIFY}, {semanage_iface_dbase_local(handle), semanage_iface_dbase_policy(handle), MODE_MODIFY}, {semanage_bool_dbase_local(handle), semanage_bool_dbase_policy(handle), MODE_SET}, {semanage_seuser_dbase_local(handle), semanage_seuser_dbase_policy(handle), MODE_MODIFY}, {semanage_node_dbase_local(handle), semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT}, {semanage_ibpkey_dbase_local(handle), semanage_ibpkey_dbase_policy(handle), MODE_MODIFY}, {semanage_ibendport_dbase_local(handle), semanage_ibendport_dbase_policy(handle), MODE_MODIFY}, }; const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]); /* Merge components into policy (and validate) */ for (i = 0; i < CCOUNT; i++) { record_t **records = NULL; unsigned int nrecords = 0; dbase_config_t *src = components[i].src; dbase_config_t *dst = components[i].dst; int mode = components[i].mode; record_table_t *rtable = src->dtable->get_rtable(src->dbase); /* Must invoke cache function first */ if (src->dtable->cache(handle, src->dbase) < 0) goto err; if (dst->dtable->cache(handle, dst->dbase) < 0) goto err; /* List all records */ if (src->dtable->list(handle, src->dbase, &records, &nrecords) < 0) goto err; /* Sort records on MODE_SORT */ if (mode & MODE_SORT) { qsort(records, nrecords, sizeof(record_t *), (int (*)(const void *, const void *))rtable-> compare2_qsort); } /* Clear obsolete ones for MODE_SET */ if (mode & MODE_SET && clear_obsolete(handle, records, nrecords, src, dst) < 0) { rc = STATUS_ERR; goto dbase_exit; } /* Load records */ if (load_records(handle, dst, records, nrecords, mode) < 0) { rc = STATUS_ERR; goto dbase_exit; } /* Cleanup */ dbase_exit: for (j = 0; j < nrecords; j++) rtable->free(records[j]); free(records); /* Abort on error */ if (rc < 0) goto err; } return rc; err: ERR(handle, "could not merge local modifications into policy"); return STATUS_ERR; } int semanage_commit_components(semanage_handle_t * handle) { int i; dbase_config_t *components[] = { semanage_iface_dbase_local(handle), semanage_bool_dbase_local(handle), semanage_user_base_dbase_local(handle), semanage_user_extra_dbase_local(handle), semanage_user_extra_dbase_policy(handle), semanage_port_dbase_local(handle), semanage_fcontext_dbase_local(handle), semanage_fcontext_dbase_policy(handle), semanage_seuser_dbase_local(handle), semanage_seuser_dbase_policy(handle), semanage_bool_dbase_active(handle), semanage_node_dbase_local(handle), semanage_ibpkey_dbase_local(handle), semanage_ibendport_dbase_local(handle), }; const int CCOUNT = sizeof(components) / sizeof(components[0]); for (i = 0; i < CCOUNT; i++) { /* Flush to disk */ if (components[i]->dtable->flush(handle, components[i]->dbase) < 0) goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not commit local/active modifications"); for (i = 0; i < CCOUNT; i++) components[i]->dtable->drop_cache(components[i]->dbase); return STATUS_ERR; } libsemanage/src/port_internal.h0100644 0000000 0000000 00000003115 13756670064 015712 0ustar000000000 0000000 #ifndef _SEMANAGE_PORT_INTERNAL_H_ #define _SEMANAGE_PORT_INTERNAL_H_ #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_port_create) hidden_proto(semanage_port_compare) hidden_proto(semanage_port_compare2) hidden_proto(semanage_port_clone) hidden_proto(semanage_port_free) hidden_proto(semanage_port_key_extract) hidden_proto(semanage_port_key_free) hidden_proto(semanage_port_get_high) hidden_proto(semanage_port_get_low) hidden_proto(semanage_port_set_port) hidden_proto(semanage_port_set_range) hidden_proto(semanage_port_get_proto) hidden_proto(semanage_port_set_proto) hidden_proto(semanage_port_get_proto_str) hidden_proto(semanage_port_get_con) hidden_proto(semanage_port_set_con) hidden_proto(semanage_port_list_local) /* PORT RECORD: method table */ extern record_table_t SEMANAGE_PORT_RTABLE; extern int port_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void port_file_dbase_release(dbase_config_t * dconfig); extern int port_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void port_policydb_dbase_release(dbase_config_t * dconfig); extern int hidden semanage_port_validate_local(semanage_handle_t * handle); /* ==== Internal (to ports) API === */ hidden int semanage_port_compare2_qsort(const semanage_port_t ** port, const semanage_port_t ** port2); #endif libsemanage/src/port_record.c0100644 0000000 0000000 00000007712 13756670064 015356 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_port_t (Network Port) * Object: semanage_port_key_t (Network Port Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include #include typedef sepol_context_t semanage_context_t; typedef sepol_port_t semanage_port_t; typedef sepol_port_key_t semanage_port_key_t; #define _SEMANAGE_PORT_DEFINED_ #define _SEMANAGE_CONTEXT_DEFINED_ typedef semanage_port_t record_t; typedef semanage_port_key_t record_key_t; #define DBASE_RECORD_DEFINED #include "port_internal.h" #include "handle.h" #include "database.h" /* Key */ int semanage_port_compare(const semanage_port_t * port, const semanage_port_key_t * key) { return sepol_port_compare(port, key); } hidden_def(semanage_port_compare) int semanage_port_compare2(const semanage_port_t * port, const semanage_port_t * port2) { return sepol_port_compare2(port, port2); } hidden_def(semanage_port_compare2) hidden int semanage_port_compare2_qsort(const semanage_port_t ** port, const semanage_port_t ** port2) { return sepol_port_compare2(*port, *port2); } int semanage_port_key_create(semanage_handle_t * handle, int low, int high, int proto, semanage_port_key_t ** key_ptr) { return sepol_port_key_create(handle->sepolh, low, high, proto, key_ptr); } int semanage_port_key_extract(semanage_handle_t * handle, const semanage_port_t * port, semanage_port_key_t ** key_ptr) { return sepol_port_key_extract(handle->sepolh, port, key_ptr); } hidden_def(semanage_port_key_extract) void semanage_port_key_free(semanage_port_key_t * key) { sepol_port_key_free(key); } hidden_def(semanage_port_key_free) /* Protocol */ int semanage_port_get_proto(const semanage_port_t * port) { return sepol_port_get_proto(port); } hidden_def(semanage_port_get_proto) void semanage_port_set_proto(semanage_port_t * port, int proto) { sepol_port_set_proto(port, proto); } hidden_def(semanage_port_set_proto) const char *semanage_port_get_proto_str(int proto) { return sepol_port_get_proto_str(proto); } hidden_def(semanage_port_get_proto_str) /* Port */ int semanage_port_get_low(const semanage_port_t * port) { return sepol_port_get_low(port); } hidden_def(semanage_port_get_low) int semanage_port_get_high(const semanage_port_t * port) { return sepol_port_get_high(port); } hidden_def(semanage_port_get_high) void semanage_port_set_port(semanage_port_t * port, int port_num) { sepol_port_set_port(port, port_num); } hidden_def(semanage_port_set_port) void semanage_port_set_range(semanage_port_t * port, int low, int high) { sepol_port_set_range(port, low, high); } hidden_def(semanage_port_set_range) /* Context */ semanage_context_t *semanage_port_get_con(const semanage_port_t * port) { return sepol_port_get_con(port); } hidden_def(semanage_port_get_con) int semanage_port_set_con(semanage_handle_t * handle, semanage_port_t * port, semanage_context_t * con) { return sepol_port_set_con(handle->sepolh, port, con); } hidden_def(semanage_port_set_con) /* Create/Clone/Destroy */ int semanage_port_create(semanage_handle_t * handle, semanage_port_t ** port_ptr) { return sepol_port_create(handle->sepolh, port_ptr); } hidden_def(semanage_port_create) int semanage_port_clone(semanage_handle_t * handle, const semanage_port_t * port, semanage_port_t ** port_ptr) { return sepol_port_clone(handle->sepolh, port, port_ptr); } hidden_def(semanage_port_clone) void semanage_port_free(semanage_port_t * port) { sepol_port_free(port); } hidden_def(semanage_port_free) /* Port base functions */ record_table_t SEMANAGE_PORT_RTABLE = { .create = semanage_port_create, .key_extract = semanage_port_key_extract, .key_free = semanage_port_key_free, .clone = semanage_port_clone, .compare = semanage_port_compare, .compare2 = semanage_port_compare2, .compare2_qsort = semanage_port_compare2_qsort, .free = semanage_port_free, }; libsemanage/src/ports_file.c0100644 0000000 0000000 00000010520 13756670064 015171 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_port; struct semanage_port_key; typedef struct semanage_port record_t; typedef struct semanage_port_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include "port_internal.h" #include "context_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int port_print(semanage_handle_t * handle, semanage_port_t * port, FILE * str) { char *con_str = NULL; int low = semanage_port_get_low(port); int high = semanage_port_get_high(port); int proto = semanage_port_get_proto(port); const char *proto_str = semanage_port_get_proto_str(proto); semanage_context_t *con = semanage_port_get_con(port); if (fprintf(str, "portcon %s ", proto_str) < 0) goto err; if (low == high) { if (fprintf(str, "%d ", low) < 0) goto err; } else { if (fprintf(str, "%d - %d ", low, high) < 0) goto err; } if (semanage_context_to_string(handle, con, &con_str) < 0) goto err; if (fprintf(str, "%s\n", con_str) < 0) goto err; free(con_str); return STATUS_SUCCESS; err: ERR(handle, "could not print port range %u - %u (%s) to stream", low, high, proto_str); free(con_str); return STATUS_ERR; } static int port_parse(semanage_handle_t * handle, parse_info_t * info, semanage_port_t * port) { int low, high; char *str = NULL; semanage_context_t *con = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Header */ if (parse_assert_str(handle, info, "portcon") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Protocol */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (!strcasecmp(str, "tcp")) semanage_port_set_proto(port, SEMANAGE_PROTO_TCP); else if (!strcasecmp(str, "udp")) semanage_port_set_proto(port, SEMANAGE_PROTO_UDP); else { ERR(handle, "invalid protocol \"%s\" (%s: %u):\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; /* Range/Port */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_fetch_int(handle, info, &low, '-') < 0) goto err; /* If range (-) does not follow immediately, require a space * In other words, the space here is optional, but only * in the ranged case, not in the single port case, * so do a custom test */ if (*(info->ptr) && *(info->ptr) != '-') { if (parse_assert_space(handle, info) < 0) goto err; } if (parse_optional_ch(info, '-') != STATUS_NODATA) { if (parse_skip_space(handle, info) < 0) goto err; if (parse_fetch_int(handle, info, &high, ' ') < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_port_set_range(port, low, high); } else semanage_port_set_port(port, low); /* Port context */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_context_from_string(handle, str, &con) < 0) { ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", str, info->filename, info->lineno, info->orig_line); goto err; } if (con == NULL) { ERR(handle, "<> context is not valid " "for ports (%s: %u):\n%s", info->filename, info->lineno, info->orig_line); goto err; } free(str); str = NULL; if (semanage_port_set_con(handle, port, con) < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; semanage_context_free(con); return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse port record"); free(str); semanage_context_free(con); parse_dispose_line(info); return STATUS_ERR; } /* PORT RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_PORT_FILE_RTABLE = { .parse = port_parse, .print = port_print, }; int port_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_PORT_RTABLE, &SEMANAGE_PORT_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void port_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/ports_local.c0100644 0000000 0000000 00000007367 13756670064 015363 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_port; struct semanage_port_key; typedef struct semanage_port_key record_key_t; typedef struct semanage_port record_t; #define DBASE_RECORD_DEFINED #include #include "port_internal.h" #include "debug.h" #include "handle.h" #include "database.h" int semanage_port_modify_local(semanage_handle_t * handle, const semanage_port_key_t * key, const semanage_port_t * data) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } int semanage_port_del_local(semanage_handle_t * handle, const semanage_port_key_t * key) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_del(handle, dconfig, key); } int semanage_port_query_local(semanage_handle_t * handle, const semanage_port_key_t * key, semanage_port_t ** response) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_port_exists_local(semanage_handle_t * handle, const semanage_port_key_t * key, int *response) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_port_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_port_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_port_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_port_list_local(semanage_handle_t * handle, semanage_port_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_port_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } hidden_def(semanage_port_list_local) int hidden semanage_port_validate_local(semanage_handle_t * handle) { semanage_port_t **ports = NULL; unsigned int nports = 0; unsigned int i = 0, j = 0; /* List and sort the ports */ if (semanage_port_list_local(handle, &ports, &nports) < 0) goto err; qsort(ports, nports, sizeof(semanage_port_t *), (int (*)(const void *, const void *)) &semanage_port_compare2_qsort); /* Test each port for overlap */ while (i < nports) { int proto = semanage_port_get_proto(ports[i]); int low = semanage_port_get_low(ports[i]); int high = semanage_port_get_high(ports[i]); const char *proto_str = semanage_port_get_proto_str(proto); const char *proto_str2; int proto2, low2, high2; /* Find the first port with matching protocol to compare against */ do { if (j == nports - 1) goto next; j++; proto2 = semanage_port_get_proto(ports[j]); low2 = semanage_port_get_low(ports[j]); high2 = semanage_port_get_high(ports[j]); proto_str2 = semanage_port_get_proto_str(proto2); } while (proto != proto2); /* Overlap detected */ if (low2 <= high) { ERR(handle, "port overlap between ranges " "%u - %u (%s) <--> %u - %u (%s).", low, high, proto_str, low2, high2, proto_str2); goto invalid; } /* If closest port of matching protocol doesn't overlap with * test port, neither do the rest of them, because that's * how the sort function works on ports - lower bound * ports come first */ next: i++; j = i; } for (i = 0; i < nports; i++) semanage_port_free(ports[i]); free(ports); return STATUS_SUCCESS; err: ERR(handle, "could not complete ports validity check"); invalid: for (i = 0; i < nports; i++) semanage_port_free(ports[i]); free(ports); return STATUS_ERR; } libsemanage/src/ports_policy.c0100644 0000000 0000000 00000002645 13756670064 015562 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_port; struct semanage_port_key; typedef struct semanage_port_key record_key_t; typedef struct semanage_port record_t; #define DBASE_RECORD_DEFINED #include "port_internal.h" #include "handle.h" #include "database.h" int semanage_port_query(semanage_handle_t * handle, const semanage_port_key_t * key, semanage_port_t ** response) { dbase_config_t *dconfig = semanage_port_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_port_exists(semanage_handle_t * handle, const semanage_port_key_t * key, int *response) { dbase_config_t *dconfig = semanage_port_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_port_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_port_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_port_iterate(semanage_handle_t * handle, int (*handler) (const semanage_port_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_port_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } int semanage_port_list(semanage_handle_t * handle, semanage_port_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_port_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/ports_policydb.c0100644 0000000 0000000 00000004307 13756670064 016065 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_port; struct semanage_port_key; typedef struct semanage_port record_t; typedef struct semanage_port_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "port_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* PORT RECORD (SEPOL): POLICYDB extension : method table */ record_policydb_table_t SEMANAGE_PORT_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t) sepol_port_modify, .set = NULL, .query = (record_policydb_table_query_t) sepol_port_query, .count = (record_policydb_table_count_t) sepol_port_count, .exists = (record_policydb_table_exists_t) sepol_port_exists, .iterate = (record_policydb_table_iterate_t) sepol_port_iterate, }; int port_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_PORT_RTABLE, &SEMANAGE_PORT_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void port_policydb_dbase_release(dbase_config_t * dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/pywrap-test.py0100644 0000000 0000000 00000136550 13756670064 015544 0ustar000000000 0000000 #!/usr/bin/env python from __future__ import print_function import sys import getopt import semanage usage = "\ Choose one of the following tests:\n\ -m for modules\n\ -u for users\n\ -U for add user (warning this will write!)\n\ -s for seusers\n\ -S for add seuser (warning this will write!)\n\ -p for ports\n\ -P for add port (warning this will write!)\n\ -f for file contexts \n\ -F for add file context (warning this will write!)\n\ -i for network interfaces \n\ -I for add network interface (warning this will write!)\n\ -b for booleans \n\ -B for add boolean (warning this will write!)\n\ -c for aCtive booleans\n\ -C for set aCtive boolean (warning this will write!)\n\n\ -n for network nodes\n\ -N for add node (warning this will write!)\n\n\ Other options:\n\ -h for this help\n\ -v for verbose output\ " class Usage(Exception): def __init__(self, msg): Exception.__init__(self) self.msg = msg class Status(Exception): def __init__(self, msg): Exception.__init__(self) self.msg = msg class Error(Exception): def __init__(self, msg): Exception.__init__(self) self.msg = msg class Tests: def __init__(self): self.all = False self.users = False self.writeuser = False self.seusers = False self.writeseuser = False self.ports = False self.writeport = False self.fcontexts = False self.writefcontext = False self.interfaces = False self.writeinterface = False self.booleans = False self.writeboolean = False self.abooleans = False self.writeaboolean = False self.nodes = False self.writenode = False self.modules = False self.verbose = False def selected(self): return ( self.all or self.users or self.modules or self.seusers or self.ports or self.fcontexts or self.interfaces or self.booleans or self.abooleans or self.writeuser or self.writeseuser or self.writeport or self.writefcontext or self.writeinterface or self.writeboolean or self.writeaboolean or self.nodes or self.writenode) def run(self, handle): if self.users or self.all: self.test_users(handle) print("") if self.seusers or self.all: self.test_seusers(handle) print("") if self.ports or self.all: self.test_ports(handle) print("") if self.modules or self.all: self.test_modules(handle) print("") if self.fcontexts or self.all: self.test_fcontexts(handle) print("") if self.interfaces or self.all: self.test_interfaces(handle) print("") if self.booleans or self.all: self.test_booleans(handle) print("") if self.abooleans or self.all: self.test_abooleans(handle) print("") if self.nodes or self.all: self.test_nodes(handle) print("") if self.writeuser or self.all: self.test_writeuser(handle) print("") if self.writeseuser or self.all: self.test_writeseuser(handle) print("") if self.writeport or self.all: self.test_writeport(handle) print("") if self.writefcontext or self.all: self.test_writefcontext(handle) print("") if self.writeinterface or self.all: self.test_writeinterface(handle) print("") if self.writeboolean or self.all: self.test_writeboolean(handle) print("") if self.writeaboolean or self.all: self.test_writeaboolean(handle) print("") if self.writenode or self.all: self.test_writenode(handle) print("") def test_modules(self, sh): print("Testing modules...") (trans_cnt, mlist, mlist_size) = semanage.semanage_module_list(sh) print("Transaction number: %s" % trans_cnt) print("Module list size: %s" % mlist_size) if self.verbose: print("List reference: %s" % mlist) if mlist_size == 0: print("No modules installed!") print("This is not necessarily a test failure.") return for idx in range(mlist_size): module = semanage.semanage_module_list_nth(mlist, idx) if self.verbose: print("Module reference: %s" % module) print("Module name: %s" % semanage.semanage_module_get_name(module)) def test_seusers(self, sh): print("Testing seusers...") (status, slist) = semanage.semanage_seuser_list(sh) if status < 0: raise Error("Could not list seusers") print("Query status (commit number): %s" % status) if len(slist) == 0: print("No seusers found!") print("This is not necessarily a test failure.") return for seuser in slist: if self.verbose: print("seseuser reference: %s" % seuser) print("seuser name: %s" % semanage.semanage_seuser_get_name(seuser)) print(" seuser mls range: %s" % semanage.semanage_seuser_get_mlsrange(seuser)) print(" seuser sename: %s" % semanage.semanage_seuser_get_sename(seuser)) semanage.semanage_seuser_free(seuser) def test_users(self, sh): print("Testing users...") (status, ulist) = semanage.semanage_user_list(sh) if status < 0: raise Error("Could not list users") print("Query status (commit number): %s" % status) if len(ulist) == 0: print("No users found!") print("This is not necessarily a test failure.") return for user in ulist: if self.verbose: print("User reference: %s" % user) print("User name: %s" % semanage.semanage_user_get_name(user)) print(" User labeling prefix: %s" % semanage.semanage_user_get_prefix(user)) print(" User mls level: %s" % semanage.semanage_user_get_mlslevel(user)) print(" User mls range: %s" % semanage.semanage_user_get_mlsrange(user)) print(" User number of roles: %s" % semanage.semanage_user_get_num_roles(user)) print(" User roles: ") (status, rlist) = semanage.semanage_user_get_roles(sh, user) if status < 0: raise Error("Could not get user roles") for role in rlist: print(" %s" % role) semanage.semanage_user_free(user) def test_ports(self, sh): print("Testing ports...") (status, plist) = semanage.semanage_port_list(sh) if status < 0: raise Error("Could not list ports") print("Query status (commit number): %s" % status) if len(plist) == 0: print("No ports found!") print("This is not necessarily a test failure.") return for port in plist: if self.verbose: print("Port reference: %s" % port) low = semanage.semanage_port_get_low(port) high = semanage.semanage_port_get_high(port) con = semanage.semanage_port_get_con(port) proto = semanage.semanage_port_get_proto(port) proto_str = semanage.semanage_port_get_proto_str(proto) if low == high: range_str = str(low) else: range_str = str(low) + "-" + str(high) (rc, con_str) = semanage.semanage_context_to_string(sh, con) if rc < 0: con_str = "" print("Port: %s %s Context: %s" % (range_str, proto_str, con_str)) semanage.semanage_port_free(port) def test_fcontexts(self, sh): print("Testing file contexts...") (status, flist) = semanage.semanage_fcontext_list(sh) if status < 0: raise Error("Could not list file contexts") print("Query status (commit number): %s" % status) if len(flist) == 0: print("No file contexts found!") print("This is not necessarily a test failure.") return for fcon in flist: if self.verbose: print("File Context reference: %s" % fcon) expr = semanage.semanage_fcontext_get_expr(fcon) type = semanage.semanage_fcontext_get_type(fcon) type_str = semanage.semanage_fcontext_get_type_str(type) con = semanage.semanage_fcontext_get_con(fcon) if not con: con_str = "<>" else: (rc, con_str) = semanage.semanage_context_to_string(sh, con) if rc < 0: con_str = "" print("File Expr: %s [%s] Context: %s" % (expr, type_str, con_str)) semanage.semanage_fcontext_free(fcon) def test_interfaces(self, sh): print("Testing network interfaces...") (status, ilist) = semanage.semanage_iface_list(sh) if status < 0: raise Error("Could not list interfaces") print("Query status (commit number): %s" % status) if len(ilist) == 0: print("No network interfaces found!") print("This is not necessarily a test failure.") return for iface in ilist: if self.verbose: print("Interface reference: %s" % iface) name = semanage.semanage_iface_get_name(iface) msg_con = semanage.semanage_iface_get_msgcon(iface) if_con = semanage.semanage_iface_get_ifcon(iface) (rc, msg_con_str) = semanage.semanage_context_to_string(sh, msg_con) if rc < 0: msg_con_str = "" (rc, if_con_str) = semanage.semanage_context_to_string(sh, if_con) if rc < 0: if_con_str = "" print("Interface: %s Context: %s Message Context: %s" % (name, if_con_str, msg_con_str)) semanage.semanage_iface_free(iface) def test_booleans(self, sh): print("Testing booleans...") (status, blist) = semanage.semanage_bool_list(sh) if status < 0: raise Error("Could not list booleans") print("Query status (commit number): %s" % status) if len(blist) == 0: print("No booleans found!") print("This is not necessarily a test failure.") return for pbool in blist: if self.verbose: print("Boolean reference: %s" % pbool) name = semanage.semanage_bool_get_name(pbool) value = semanage.semanage_bool_get_value(pbool) print("Boolean: %s Value: %s" % (name, value)) semanage.semanage_bool_free(pbool) def test_abooleans(self, sh): print("Testing active booleans...") (status, ablist) = semanage.semanage_bool_list_active(sh) if status < 0: raise Error("Could not list active booleans") print("Query status (commit number): %s" % status) if len(ablist) == 0: print("No active booleans found!") print("This is not necessarily a test failure.") return for abool in ablist: if self.verbose: print("Active boolean reference: %s" % abool) name = semanage.semanage_bool_get_name(abool) value = semanage.semanage_bool_get_value(abool) print("Active Boolean: %s Value: %s" % (name, value)) semanage.semanage_bool_free(abool) def test_nodes(self, sh): print("Testing network nodes...") (status, nlist) = semanage.semanage_node_list(sh) if status < 0: raise Error("Could not list network nodes") print("Query status (commit number): %s" % status) if len(nlist) == 0: print("No network nodes found!") print("This is not necessarily a test failure.") return for node in nlist: if self.verbose: print("Network node reference: %s" % node) (status, addr) = semanage.semanage_node_get_addr(sh, node) if status < 0: addr = "" (status, mask) = semanage.semanage_node_get_mask(sh, node) if status < 0: mask = "" proto = semanage.semanage_node_get_proto(node) proto_str = semanage.semanage_node_get_proto_str(proto) con = semanage.semanage_node_get_con(node) (status, con_str) = semanage.semanage_context_to_string(sh, con) if status < 0: con_str = "" print("Network Node: %s/%s (%s) Context: %s" % (addr, mask, proto_str, con_str)) semanage.semanage_node_free(node) def test_writeuser(self, sh): print("Testing user write...") (status, user) = semanage.semanage_user_create(sh) if status < 0: raise Error("Could not create user object") if self.verbose: print("User object created") status = semanage.semanage_user_set_name(sh, user, "testPyUser") if status < 0: raise Error("Could not set user name") if self.verbose: print("User name set: %s" % semanage.semanage_user_get_name(user)) status = semanage.semanage_user_add_role(sh, user, "user_r") if status < 0: raise Error("Could not add role") status = semanage.semanage_user_set_prefix(sh, user, "user") if status < 0: raise Error("Could not set labeling prefix") if self.verbose: print("User prefix set: %s" % semanage.semanage_user_get_prefix(user)) status = semanage.semanage_user_set_mlsrange(sh, user, "s0") if status < 0: raise Error("Could not set MLS range") if self.verbose: print("User mlsrange: %s" % semanage.semanage_user_get_mlsrange(user)) status = semanage.semanage_user_set_mlslevel(sh, user, "s0") if status < 0: raise Error("Could not set MLS level") if self.verbose: print("User mlslevel: %s" % semanage.semanage_user_get_mlslevel(user)) (status, key) = semanage.semanage_user_key_extract(sh, user) if status < 0: raise Error("Could not extract user key") if self.verbose: print("User key extracted: %s" % key) (status, exists) = semanage.semanage_user_exists_local(sh, key) if status < 0: raise Error("Could not check if user exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_user) = semanage.semanage_user_query_local(sh, key) if status < 0: raise Error("Could not query old user") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction..") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_user_modify_local(sh, key, user) if status < 0: raise Error("Could not modify user") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing user...") status = semanage.semanage_user_del_local(sh, key) if status < 0: raise Error("Could not delete test user") if self.verbose: print("User delete: %s" % status) else: print("Resetting user...") status = semanage.semanage_user_modify_local(sh, key, old_user) if status < 0: raise Error("Could not reset test user") if self.verbose: print("User modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_user_key_free(key) semanage.semanage_user_free(user) if exists: semanage.semanage_user_free(old_user) def test_writeseuser(self, sh): print("Testing seuser write...") (status, seuser) = semanage.semanage_seuser_create(sh) if status < 0: raise Error("Could not create SEUser object") if self.verbose: print("SEUser object created.") status = semanage.semanage_seuser_set_name(sh, seuser, "testPySEUser") if status < 0: raise Error("Could not set name") if self.verbose: print("SEUser name set: %s" % semanage.semanage_seuser_get_name(seuser)) status = semanage.semanage_seuser_set_sename(sh, seuser, "root") if status < 0: raise Error("Could not set sename") if self.verbose: print("SEUser seuser: %s" % semanage.semanage_seuser_get_sename(seuser)) status = semanage.semanage_seuser_set_mlsrange(sh, seuser, "s0:c0.c255") if status < 0: raise Error("Could not set MLS range") if self.verbose: print("SEUser mlsrange: %s" % semanage.semanage_seuser_get_mlsrange(seuser)) (status, key) = semanage.semanage_seuser_key_extract(sh, seuser) if status < 0: raise Error("Could not extract SEUser key") if self.verbose: print("SEUser key extracted: %s" % key) (status, exists) = semanage.semanage_seuser_exists_local(sh, key) if status < 0: raise Error("Could not check if SEUser exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_seuser) = semanage.semanage_seuser_query_local(sh, key) if status < 0: raise Error("Could not query old SEUser") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_seuser_modify_local(sh, key, seuser) if status < 0: raise Error("Could not modify SEUser") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing seuser...") status = semanage.semanage_seuser_del_local(sh, key) if status < 0: raise Error("Could not delete test SEUser") if self.verbose: print("Seuser delete: %s" % status) else: print("Resetting seuser...") status = semanage.semanage_seuser_modify_local(sh, key, old_seuser) if status < 0: raise Error("Could not reset test SEUser") if self.verbose: print("Seuser modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_seuser_key_free(key) semanage.semanage_seuser_free(seuser) if exists: semanage.semanage_seuser_free(old_seuser) def test_writeport(self, sh): print("Testing port write...") (status, port) = semanage.semanage_port_create(sh) if status < 0: raise Error("Could not create SEPort object") if self.verbose: print("SEPort object created.") semanage.semanage_port_set_range(port, 150, 200) low = semanage.semanage_port_get_low(port) high = semanage.semanage_port_get_high(port) if self.verbose: print("SEPort range set: %s-%s" % (low, high)) semanage.semanage_port_set_proto(port, semanage.SEMANAGE_PROTO_TCP) if self.verbose: print("SEPort protocol set: %s" % semanage.semanage_port_get_proto_str(semanage.SEMANAGE_PROTO_TCP)) (status, con) = semanage.semanage_context_create(sh) if status < 0: raise Error("Could not create SEContext object") if self.verbose: print("SEContext object created (for port).") status = semanage.semanage_context_set_user(sh, con, "system_u") if status < 0: raise Error("Could not set context user") if self.verbose: print("SEContext user: %s" % semanage.semanage_context_get_user(con)) status = semanage.semanage_context_set_role(sh, con, "object_r") if status < 0: raise Error("Could not set context role") if self.verbose: print("SEContext role: %s" % semanage.semanage_context_get_role(con)) status = semanage.semanage_context_set_type(sh, con, "http_port_t") if status < 0: raise Error("Could not set context type") if self.verbose: print("SEContext type: %s" % semanage.semanage_context_get_type(con)) status = semanage.semanage_context_set_mls(sh, con, "s0:c0.c255") if status < 0: raise Error("Could not set context MLS fields") if self.verbose: print("SEContext mls: %s" % semanage.semanage_context_get_mls(con)) status = semanage.semanage_port_set_con(sh, port, con) if status < 0: raise Error("Could not set SEPort context") if self.verbose: print("SEPort context set: %s" % con) (status, key) = semanage.semanage_port_key_extract(sh, port) if status < 0: raise Error("Could not extract SEPort key") if self.verbose: print("SEPort key extracted: %s" % key) (status, exists) = semanage.semanage_port_exists_local(sh, key) if status < 0: raise Error("Could not check if SEPort exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_port) = semanage.semanage_port_query_local(sh, key) if status < 0: raise Error("Could not query old SEPort") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_port_modify_local(sh, key, port) if status < 0: raise Error("Could not modify SEPort") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing port range...") status = semanage.semanage_port_del_local(sh, key) if status < 0: raise Error("Could not delete test SEPort") if self.verbose: print("Port range delete: %s" % status) else: print("Resetting port range...") status = semanage.semanage_port_modify_local(sh, key, old_port) if status < 0: raise Error("Could not reset test SEPort") if self.verbose: print("Port range modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_context_free(con) semanage.semanage_port_key_free(key) semanage.semanage_port_free(port) if exists: semanage.semanage_port_free(old_port) def test_writefcontext(self, sh): print("Testing file context write...") (status, fcon) = semanage.semanage_fcontext_create(sh) if status < 0: raise Error("Could not create SEFcontext object") if self.verbose: print("SEFcontext object created.") status = semanage.semanage_fcontext_set_expr(sh, fcon, "/test/fcontext(/.*)?") if status < 0: raise Error("Could not set expression") if self.verbose: print("SEFContext expr set: %s" % semanage.semanage_fcontext_get_expr(fcon)) semanage.semanage_fcontext_set_type(fcon, semanage.SEMANAGE_FCONTEXT_REG) if self.verbose: ftype = semanage.semanage_fcontext_get_type(fcon) print("SEFContext type set: %s" % semanage.semanage_fcontext_get_type_str(ftype)) (status, con) = semanage.semanage_context_create(sh) if status < 0: raise Error("Could not create SEContext object") if self.verbose: print("SEContext object created (for file context).") status = semanage.semanage_context_set_user(sh, con, "system_u") if status < 0: raise Error("Could not set context user") if self.verbose: print("SEContext user: %s" % semanage.semanage_context_get_user(con)) status = semanage.semanage_context_set_role(sh, con, "object_r") if status < 0: raise Error("Could not set context role") if self.verbose: print("SEContext role: %s" % semanage.semanage_context_get_role(con)) status = semanage.semanage_context_set_type(sh, con, "default_t") if status < 0: raise Error("Could not set context type") if self.verbose: print("SEContext type: %s" % semanage.semanage_context_get_type(con)) status = semanage.semanage_context_set_mls(sh, con, "s0:c0.c255") if status < 0: raise Error("Could not set context MLS fields") if self.verbose: print("SEContext mls: %s" % semanage.semanage_context_get_mls(con)) status = semanage.semanage_fcontext_set_con(sh, fcon, con) if status < 0: raise Error("Could not set SEFcontext context") if self.verbose: print("SEFcontext context set: %s" % con) (status, key) = semanage.semanage_fcontext_key_extract(sh, fcon) if status < 0: raise Error("Could not extract SEFcontext key") if self.verbose: print("SEFcontext key extracted: %s" % key) (status, exists) = semanage.semanage_fcontext_exists_local(sh, key) if status < 0: raise Error("Could not check if SEFcontext exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_fcontext) = semanage.semanage_fcontext_query_local(sh, key) if status < 0: raise Error("Could not query old SEFcontext") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_fcontext_modify_local(sh, key, fcon) if status < 0: raise Error("Could not modify SEFcontext") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing file context...") status = semanage.semanage_fcontext_del_local(sh, key) if status < 0: raise Error("Could not delete test SEFcontext") if self.verbose: print("File context delete: %s" % status) else: print("Resetting file context...") status = semanage.semanage_fcontext_modify_local(sh, key, old_fcontext) if status < 0: raise Error("Could not reset test FContext") if self.verbose: print("File context modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_context_free(con) semanage.semanage_fcontext_key_free(key) semanage.semanage_fcontext_free(fcon) if exists: semanage.semanage_fcontext_free(old_fcontext) def test_writeinterface(self, sh): print("Testing network interface write...") (status, iface) = semanage.semanage_iface_create(sh) if status < 0: raise Error("Could not create SEIface object") if self.verbose: print("SEIface object created.") status = semanage.semanage_iface_set_name(sh, iface, "test_iface") if status < 0: raise Error("Could not set SEIface name") if self.verbose: print("SEIface name set: %s" % semanage.semanage_iface_get_name(iface)) (status, con) = semanage.semanage_context_create(sh) if status < 0: raise Error("Could not create SEContext object") if self.verbose: print("SEContext object created (for network interface)") status = semanage.semanage_context_set_user(sh, con, "system_u") if status < 0: raise Error("Could not set interface context user") if self.verbose: print("SEContext user: %s" % semanage.semanage_context_get_user(con)) status = semanage.semanage_context_set_role(sh, con, "object_r") if status < 0: raise Error("Could not set interface context role") if self.verbose: print("SEContext role: %s" % semanage.semanage_context_get_role(con)) status = semanage.semanage_context_set_type(sh, con, "default_t") if status < 0: raise Error("Could not set interface context type") if self.verbose: print("SEContext type: %s" % semanage.semanage_context_get_type(con)) status = semanage.semanage_context_set_mls(sh, con, "s0:c0.c255") if status < 0: raise Error("Could not set interface context MLS fields") if self.verbose: print("SEContext mls: %s" % semanage.semanage_context_get_mls(con)) status = semanage.semanage_iface_set_ifcon(sh, iface, con) if status < 0: raise Error("Could not set SEIface interface context") if self.verbose: print("SEIface interface context set: %s" % con) status = semanage.semanage_iface_set_msgcon(sh, iface, con) if status < 0: raise Error("Could not set SEIface message context") if self.verbose: print("SEIface message context set: %s" % con) (status, key) = semanage.semanage_iface_key_extract(sh, iface) if status < 0: raise Error("Could not extract SEIface key") if self.verbose: print("SEIface key extracted: %s" % key) (status, exists) = semanage.semanage_iface_exists_local(sh, key) if status < 0: raise Error("Could not check if SEIface exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_iface) = semanage.semanage_iface_query_local(sh, key) if status < 0: raise Error("Could not query old SEIface") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not begin semanage transaction") status = semanage.semanage_iface_modify_local(sh, key, iface) if status < 0: raise Error("Could not modify SEIface") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not begin semanage transaction") if not exists: print("Removing interface...") status = semanage.semanage_iface_del_local(sh, key) if status < 0: raise Error("Could not delete test SEIface") if self.verbose: print("Interface delete: %s" % status) else: print("Resetting interface...") status = semanage.semanage_iface_modify_local(sh, key, old_iface) if status < 0: raise Error("Could not reset test SEIface") if self.verbose: print("Interface modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_context_free(con) semanage.semanage_iface_key_free(key) semanage.semanage_iface_free(iface) if exists: semanage.semanage_iface_free(old_iface) def test_writeboolean(self, sh): print("Testing boolean write...") (status, pbool) = semanage.semanage_bool_create(sh) if status < 0: raise Error("Could not create SEBool object") if self.verbose: print("SEBool object created.") status = semanage.semanage_bool_set_name(sh, pbool, "allow_execmem") if status < 0: raise Error("Could not set name") if self.verbose: print("SEBool name set: %s" % semanage.semanage_bool_get_name(pbool)) semanage.semanage_bool_set_value(pbool, 0) if self.verbose: print("SEbool value set: %s" % semanage.semanage_bool_get_value(pbool)) (status, key) = semanage.semanage_bool_key_extract(sh, pbool) if status < 0: raise Error("Could not extract SEBool key") if self.verbose: print("SEBool key extracted: %s" % key) (status, exists) = semanage.semanage_bool_exists_local(sh, key) if status < 0: raise Error("Could not check if SEBool exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_bool) = semanage.semanage_bool_query_local(sh, key) if status < 0: raise Error("Could not query old SEBool") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_bool_modify_local(sh, key, pbool) if status < 0: raise Error("Could not modify SEBool") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing boolean...") status = semanage.semanage_bool_del_local(sh, key) if status < 0: raise Error("Could not delete test SEBool") if self.verbose: print("Boolean delete: %s" % status) else: print("Resetting boolean...") status = semanage.semanage_bool_modify_local(sh, key, old_bool) if status < 0: raise Error("Could not reset test SEBool") if self.verbose: print("Boolean modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_bool_key_free(key) semanage.semanage_bool_free(pbool) if exists: semanage.semanage_bool_free(old_bool) def test_writeaboolean(self, sh): print("Testing active boolean write...") (status, key) = semanage.semanage_bool_key_create(sh, "allow_execmem") if status < 0: raise Error("Could not create SEBool key") if self.verbose: print("SEBool key created: %s" % key) (status, old_bool) = semanage.semanage_bool_query_active(sh, key) if status < 0: raise Error("Could not query old SEBool") if self.verbose: print("Query status (commit number): %s" % status) (status, abool) = semanage.semanage_bool_create(sh) if status < 0: raise Error("Could not create SEBool object") if self.verbose: print("SEBool object created.") status = semanage.semanage_bool_set_name(sh, abool, "allow_execmem") if status < 0: raise Error("Could not set name") if self.verbose: print("SEBool name set: %s" % semanage.semanage_bool_get_name(abool)) semanage.semanage_bool_set_value(abool, 0) if self.verbose: print("SEbool value set: %s" % semanage.semanage_bool_get_value(abool)) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_bool_set_active(sh, key, abool) if status < 0: raise Error("Could not modify SEBool") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) print("Resetting old active boolean...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_bool_set_active(sh, key, old_bool) if status < 0: raise Error("Could not reset test SEBool") if self.verbose: print("SEBool active reset: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_bool_key_free(key) semanage.semanage_bool_free(abool) semanage.semanage_bool_free(old_bool) def test_writenode(self, sh): print("Testing network node write...") (status, node) = semanage.semanage_node_create(sh) if status < 0: raise Error("Could not create SENode object") if self.verbose: print("SENode object created.") status = semanage.semanage_node_set_addr(sh, node, semanage.SEMANAGE_PROTO_IP6, "ffee:dddd::bbbb") if status < 0: raise Error("Could not set SENode address") status = semanage.semanage_node_set_mask(sh, node, semanage.SEMANAGE_PROTO_IP6, "::ffff:ffff:abcd:0000") if status < 0: raise Error("Could not set SENode netmask") semanage.semanage_node_set_proto(node, semanage.SEMANAGE_PROTO_IP6) if self.verbose: print("SENode protocol set: %s" % semanage.semanage_node_get_proto_str(semanage.SEMANAGE_PROTO_IP6)) (status, con) = semanage.semanage_context_create(sh) if status < 0: raise Error("Could not create SEContext object") if self.verbose: print("SEContext object created (for node).") status = semanage.semanage_context_set_user(sh, con, "system_u") if status < 0: raise Error("Could not set context user") if self.verbose: print("SEContext user: %s" % semanage.semanage_context_get_user(con)) status = semanage.semanage_context_set_role(sh, con, "object_r") if status < 0: raise Error("Could not set context role") if self.verbose: print("SEContext role: %s" % semanage.semanage_context_get_role(con)) status = semanage.semanage_context_set_type(sh, con, "lo_node_t") if status < 0: raise Error("Could not set context type") if self.verbose: print("SEContext type: %s" % semanage.semanage_context_get_type(con)) status = semanage.semanage_context_set_mls(sh, con, "s0:c0.c255") if status < 0: raise Error("Could not set context MLS fields") if self.verbose: print("SEContext mls: %s" % semanage.semanage_context_get_mls(con)) status = semanage.semanage_node_set_con(sh, node, con) if status < 0: raise Error("Could not set SENode context") if self.verbose: print("SENode context set: %s" % con) (status, key) = semanage.semanage_node_key_extract(sh, node) if status < 0: raise Error("Could not extract SENode key") if self.verbose: print("SENode key extracted: %s" % key) (status, exists) = semanage.semanage_node_exists_local(sh, key) if status < 0: raise Error("Could not check if SENode exists") if self.verbose: print("Exists status (commit number): %s" % status) if exists: (status, old_node) = semanage.semanage_node_query_local(sh, key) if status < 0: raise Error("Could not query old SENode") if self.verbose: print("Query status (commit number): %s" % status) print("Starting transaction...") status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") status = semanage.semanage_node_modify_local(sh, key, node) if status < 0: raise Error("Could not modify SENode") status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit test transaction") print("Commit status (transaction number): %s" % status) status = semanage.semanage_begin_transaction(sh) if status < 0: raise Error("Could not start semanage transaction") if not exists: print("Removing network node...") status = semanage.semanage_node_del_local(sh, key) if status < 0: raise Error("Could not delete test SENode") if self.verbose: print("Network node delete: %s" % status) else: print("Resetting network node...") status = semanage.semanage_node_modify_local(sh, key, old_node) if status < 0: raise Error("Could not reset test SENode") if self.verbose: print("Network node modify: %s" % status) status = semanage.semanage_commit(sh) if status < 0: raise Error("Could not commit reset transaction") print("Commit status (transaction number): %s" % status) semanage.semanage_context_free(con) semanage.semanage_node_key_free(key) semanage.semanage_node_free(node) if exists: semanage.semanage_node_free(old_node) def main(argv=None): if argv is None: argv = sys.argv try: try: opts, args = getopt.getopt( argv[1:], "hvmuspfibcUSPFIBCanN", [ "help", "verbose", "modules", "users", "seusers", "ports", "file contexts", "network interfaces", "booleans", "active booleans", "network nodes", "writeuser", "writeseuser", "writeport", "writefcontext", "writeinterface", "writeboolean", "writeaboolean", "writenode", "all", ]) tests = Tests() for o, a in opts: if o == "-v": tests.verbose = True print("Verbose output selected.") if o == "-a": tests.all = True if o == "-u": tests.users = True if o == "-U": tests.writeuser = True if o == "-s": tests.seusers = True if o == "-S": tests.writeseuser = True if o == "-p": tests.ports = True if o == "-P": tests.writeport = True if o == "-f": tests.fcontexts = True if o == "-F": tests.writefcontext = True if o == "-i": tests.interfaces = True if o == "-I": tests.writeinterface = True if o == "-b": tests.booleans = True if o == "-B": tests.writeboolean = True if o == "-c": tests.abooleans = True if o == "-C": tests.writeaboolean = True if o == "-n": tests.nodes = True if o == "-N": tests.writenode = True if o == "-m": tests.modules = True if o == "-h": raise Usage(usage) if not tests.selected(): raise Usage("Please select a valid test.") except getopt.error as msg: raise Usage(msg) sh = semanage.semanage_handle_create() if semanage.semanage_is_managed(sh) != 1: raise Status("Unmanaged!") status = semanage.semanage_connect(sh) if status < 0: raise Error("Could not establish semanage connection") tests.run(sh) status = semanage.semanage_disconnect(sh) if status < 0: raise Error("Could not disconnect") semanage.semanage_handle_destroy(sh) except Usage as err: print(err.msg, file=sys.stderr) except Status as err: print(err.msg, file=sys.stderr) except Error as err: print(err.msg, file=sys.stderr) return 2 if __name__ == "__main__": sys.exit(main()) libsemanage/src/semanage.conf0100644 0000000 0000000 00000003560 13756670064 015314 0ustar000000000 0000000 # Authors: Jason Tang # # Copyright (C) 2004-2005 Tresys Technology, LLC # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # Specify how libsemanage will interact with a SELinux policy manager. # The four options are: # # "source" - libsemanage manipulates a source SELinux policy # "direct" - libsemanage will write directly to a module store. # /foo/bar - Write by way of a policy management server, whose # named socket is at /foo/bar. The path must begin # with a '/'. # foo.com:4242 - Establish a TCP connection to a remote policy # management server at foo.com. If there is a colon # then the remainder is interpreted as a port number; # otherwise default to port 4242. module-store = direct # When generating the final linked and expanded policy, by default # semanage will set the policy version to POLICYDB_VERSION_MAX, as # given in . Change this setting if a different # version is necessary. #policy-version = 19 # By default, semanage will generate policies for the SELinux target. # To build policies for Xen, uncomment the following line. #target-platform = xen libsemanage/src/semanage_conf.h0100644 0000000 0000000 00000004352 13756670064 015623 0ustar000000000 0000000 /* Authors: Jason Tang * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEMANAGE_CONF_H #define SEMANAGE_CONF_H #include #include #include /* libsemanage has its own configuration file. It has two main parts: * - single options * - external programs to execute whenever a policy is to be loaded */ typedef struct semanage_conf { enum semanage_connect_type store_type; char *store_path; /* used for both socket path and policy dir */ char *compiler_directory_path; int server_port; int policyvers; /* version for server generated policies */ int target_platform; int expand_check; int save_previous; int save_linked; int disable_genhomedircon; int usepasswd; int handle_unknown; mode_t file_mode; int bzip_blocksize; int bzip_small; int remove_hll; int ignore_module_cache; char *ignoredirs; /* ";" separated of list for genhomedircon to ignore */ struct external_prog *load_policy; struct external_prog *setfiles; struct external_prog *sefcontext_compile; struct external_prog *mod_prog, *linked_prog, *kernel_prog; char *store_root_path; } semanage_conf_t; /* A linked list of verification programs. Each one is called in * order of appearance within the configuration file. */ typedef struct external_prog { char *path; char *args; struct external_prog *next; } external_prog_t; semanage_conf_t *semanage_conf_parse(const char *config_filename); void semanage_conf_destroy(semanage_conf_t * conf); #endif libsemanage/src/semanage_store.c0100644 0000000 0000000 00000223306 13756670064 016027 0ustar000000000 0000000 /* Authors: Karl MacMillan * Joshua Brindle * Jason Tang * Christopher Ashworth * Chris PeBenito * Caleb Case * * Copyright (C) 2004-2006,2009 Tresys Technology, LLC * Copyright (C) 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file contains semanage routines that manipulate the files on a * local module store. Sandbox routines, used by both source and * direct connections, are here as well. */ struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include "semanage_store.h" #include "database_policydb.h" #include "handle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "utilities.h" #define SEMANAGE_CONF_FILE "semanage.conf" /* relative path names to enum semanage_paths to special files and * directories for the module store */ #define TRUE 1 enum semanage_file_defs { SEMANAGE_ROOT, SEMANAGE_TRANS_LOCK, SEMANAGE_READ_LOCK, SEMANAGE_NUM_FILES }; static char *semanage_paths[SEMANAGE_NUM_STORES][SEMANAGE_STORE_NUM_PATHS]; static char *semanage_files[SEMANAGE_NUM_FILES] = { NULL }; static int semanage_paths_initialized = 0; /* These are paths relative to the bottom of the module store */ static const char *semanage_relative_files[SEMANAGE_NUM_FILES] = { "", "/semanage.trans.LOCK", "/semanage.read.LOCK" }; static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = { "/active", "/previous", "/tmp" }; /* relative path names to enum sandbox_paths for special files within * a sandbox */ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = { "", "/modules", "/policy.linked", "/homedir_template", "/file_contexts.template", "/commit_num", "/pkeys.local", "/ibendports.local", "/ports.local", "/interfaces.local", "/nodes.local", "/booleans.local", "/seusers.local", "/seusers.linked", "/users.local", "/users_extra.local", "/users_extra.linked", "/users_extra", "/disable_dontaudit", "/preserve_tunables", "/modules/disabled", "/policy.kern", "/file_contexts.local", "/file_contexts.homedirs", "/file_contexts", "/seusers" }; static char const * const semanage_final_prefix[SEMANAGE_FINAL_NUM] = { "/final", "", }; static char *semanage_final[SEMANAGE_FINAL_NUM] = { NULL }; static char *semanage_final_suffix[SEMANAGE_FINAL_PATH_NUM] = { NULL }; static char *semanage_final_paths[SEMANAGE_FINAL_NUM][SEMANAGE_FINAL_PATH_NUM] = {{ NULL }}; /* A node used in a linked list of file contexts; used for sorting. */ typedef struct semanage_file_context_node { char *path; char *file_type; char *context; int path_len; int effective_len; int type_len; int context_len; int meta; /* position of first meta char in path, -1 if none */ struct semanage_file_context_node *next; } semanage_file_context_node_t; /* A node used in a linked list of buckets that contain * semanage_file_context_node lists. Used for sorting. */ typedef struct semanage_file_context_bucket { semanage_file_context_node_t *data; struct semanage_file_context_bucket *next; } semanage_file_context_bucket_t; /* A node used in a linked list of netfilter rules. */ typedef struct semanage_netfilter_context_node { char *rule; size_t rule_len; struct semanage_netfilter_context_node *next; } semanage_netfilter_context_node_t; /* Initialize the paths to config file, lock files and store root. */ static int semanage_init_paths(const char *root) { size_t len, prefix_len; int i; if (!root) return -1; prefix_len = strlen(root); for (i = 0; i < SEMANAGE_NUM_FILES; i++) { len = (strlen(semanage_relative_files[i]) + prefix_len); semanage_files[i] = calloc(len + 1, sizeof(char)); if (!semanage_files[i]) return -1; sprintf(semanage_files[i], "%s%s", root, semanage_relative_files[i]); } return 0; } /* This initializes the paths inside the stores, this is only necessary * when directly accessing the store */ static int semanage_init_store_paths(const char *root) { int i, j; size_t len; size_t prefix_len; if (!root) return -1; prefix_len = strlen(root); for (i = 0; i < SEMANAGE_NUM_STORES; i++) { for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) { len = prefix_len + strlen(semanage_store_paths[i]) + strlen(semanage_sandbox_paths[j]); semanage_paths[i][j] = calloc(len + 1, sizeof(char)); if (!semanage_paths[i][j]) goto cleanup; sprintf(semanage_paths[i][j], "%s%s%s", root, semanage_store_paths[i], semanage_sandbox_paths[j]); } } cleanup: return 0; } static int semanage_init_final(semanage_handle_t *sh, const char *prefix) { assert(sh); assert(prefix); int status = 0; size_t len; const char *store_path = sh->conf->store_path; size_t store_len = strlen(store_path); /* SEMANAGE_FINAL_TMP */ len = strlen(semanage_root()) + strlen(prefix) + strlen("/") + strlen(semanage_final_prefix[SEMANAGE_FINAL_TMP]) + store_len; semanage_final[SEMANAGE_FINAL_TMP] = malloc(len + 1); if (semanage_final[SEMANAGE_FINAL_TMP] == NULL) { status = -1; goto cleanup; } sprintf(semanage_final[SEMANAGE_FINAL_TMP], "%s%s%s/%s", semanage_root(), prefix, semanage_final_prefix[SEMANAGE_FINAL_TMP], store_path); /* SEMANAGE_FINAL_SELINUX */ const char *selinux_root = selinux_path(); len = strlen(semanage_root()) + strlen(selinux_root) + strlen(semanage_final_prefix[SEMANAGE_FINAL_SELINUX]) + store_len; semanage_final[SEMANAGE_FINAL_SELINUX] = malloc(len + 1); if (semanage_final[SEMANAGE_FINAL_SELINUX] == NULL) { status = -1; goto cleanup; } sprintf(semanage_final[SEMANAGE_FINAL_SELINUX], "%s%s%s%s", semanage_root(), selinux_root, semanage_final_prefix[SEMANAGE_FINAL_SELINUX], store_path); cleanup: if (status != 0) { int i; for (i = 0; i < SEMANAGE_FINAL_NUM; i++) { free(semanage_final[i]); semanage_final[i] = NULL; } } return status; } static int semanage_init_final_suffix(semanage_handle_t *sh) { int ret = 0; int status = 0; char path[PATH_MAX]; size_t offset = strlen(selinux_policy_root()); semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] = strdup(""); if (semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] == NULL) { ERR(sh, "Unable to allocate space for policy top level path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_FC] = strdup(selinux_file_context_path() + offset); if (semanage_final_suffix[SEMANAGE_FC] == NULL) { ERR(sh, "Unable to allocate space for file context path."); status = -1; goto cleanup; } if (asprintf(&semanage_final_suffix[SEMANAGE_FC_BIN], "%s.bin", semanage_final_suffix[SEMANAGE_FC]) < 0) { ERR(sh, "Unable to allocate space for file context path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] = strdup(selinux_file_context_homedir_path() + offset); if (semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] == NULL) { ERR(sh, "Unable to allocate space for file context home directory path."); status = -1; goto cleanup; } if (asprintf(&semanage_final_suffix[SEMANAGE_FC_HOMEDIRS_BIN], "%s.bin", semanage_final_suffix[SEMANAGE_FC_HOMEDIRS]) < 0) { ERR(sh, "Unable to allocate space for file context home directory path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_FC_LOCAL] = strdup(selinux_file_context_local_path() + offset); if (semanage_final_suffix[SEMANAGE_FC_LOCAL] == NULL) { ERR(sh, "Unable to allocate space for local file context path."); status = -1; goto cleanup; } if (asprintf(&semanage_final_suffix[SEMANAGE_FC_LOCAL_BIN], "%s.bin", semanage_final_suffix[SEMANAGE_FC_LOCAL]) < 0) { ERR(sh, "Unable to allocate space for local file context path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_NC] = strdup(selinux_netfilter_context_path() + offset); if (semanage_final_suffix[SEMANAGE_NC] == NULL) { ERR(sh, "Unable to allocate space for netfilter context path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_SEUSERS] = strdup(selinux_usersconf_path() + offset); if (semanage_final_suffix[SEMANAGE_SEUSERS] == NULL) { ERR(sh, "Unable to allocate space for userconf path."); status = -1; goto cleanup; } ret = snprintf(path, sizeof(path), "%s.%d", selinux_binary_policy_path() + offset, sh->conf->policyvers); if (ret < 0 || ret >= (int)sizeof(path)) { ERR(sh, "Unable to compose policy binary path."); status = -1; goto cleanup; } semanage_final_suffix[SEMANAGE_KERNEL] = strdup(path); if (semanage_final_suffix[SEMANAGE_KERNEL] == NULL) { ERR(sh, "Unable to allocate space for policy binary path."); status = -1; goto cleanup; } cleanup: if (status != 0) { int i; for (i = 0; i < SEMANAGE_FINAL_PATH_NUM; i++) { free(semanage_final_suffix[i]); semanage_final_suffix[i] = NULL; } } return status; } /* Initialize final paths. */ static int semanage_init_final_paths(semanage_handle_t *sh) { int status = 0; int i, j; size_t len; for (i = 0; i < SEMANAGE_FINAL_NUM; i++) { for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) { len = strlen(semanage_final[i]) + strlen(semanage_final_suffix[j]); semanage_final_paths[i][j] = malloc(len + 1); if (semanage_final_paths[i][j] == NULL) { ERR(sh, "Unable to allocate space for policy final path."); status = -1; goto cleanup; } sprintf(semanage_final_paths[i][j], "%s%s", semanage_final[i], semanage_final_suffix[j]); } } cleanup: if (status != 0) { for (i = 0; i < SEMANAGE_FINAL_NUM; i++) { for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) { free(semanage_final_paths[i][j]); semanage_final_paths[i][j] = NULL; } } } return status; } /* THIS MUST BE THE FIRST FUNCTION CALLED IN THIS LIBRARY. If the * library has nnot been initialized yet then call the functions that * initialize the path variables. This function does nothing if it * was previously called and that call was successful. Return 0 on * success, -1 on error. * * Note that this function is NOT thread-safe. */ int semanage_check_init(semanage_handle_t *sh, const char *prefix) { int rc; if (semanage_paths_initialized == 0) { char root[PATH_MAX]; rc = snprintf(root, sizeof(root), "%s%s/%s", semanage_root(), prefix, sh->conf->store_path); if (rc < 0 || rc >= (int)sizeof(root)) return -1; rc = semanage_init_paths(root); if (rc) return rc; rc = semanage_init_store_paths(root); if (rc) return rc; rc = semanage_init_final(sh, prefix); if (rc) return rc; rc = semanage_init_final_suffix(sh); if (rc) return rc; rc = semanage_init_final_paths(sh); if (rc) return rc; semanage_paths_initialized = 1; } return 0; } /* Given a definition number, return a file name from the paths array */ const char *semanage_fname(enum semanage_sandbox_defs file_enum) { return semanage_sandbox_paths[file_enum]; } /* Given a store location (active/previous/tmp) and a definition * number, return a fully-qualified path to that file or directory. * The caller must not alter the string returned (and hence why this * function return type is const). * * This function shall never return a NULL, assuming that * semanage_check_init() was previously called. */ const char *semanage_path(enum semanage_store_defs store, enum semanage_sandbox_defs path_name) { assert(semanage_paths[store][path_name]); return semanage_paths[store][path_name]; } /* Given a store location (tmp or selinux) and a definition * number, return a fully-qualified path to that file or directory. * The caller must not alter the string returned (and hence why this * function return type is const). * * This function shall never return a NULL, assuming that * semanage_check_init() was previously called. */ const char *semanage_final_path(enum semanage_final_defs store, enum semanage_final_path_defs path_name) { assert(semanage_final_paths[store][path_name]); return semanage_final_paths[store][path_name]; } /* Return a fully-qualified path + filename to the semanage * configuration file. If semanage.conf file in the semanage * root is cannot be read, use the default semanage.conf as a * fallback. * * The caller is responsible for freeing the returned string. */ char *semanage_conf_path(void) { char *semanage_conf = NULL; int len; struct stat sb; len = strlen(semanage_root()) + strlen(selinux_path()) + strlen(SEMANAGE_CONF_FILE); semanage_conf = calloc(len + 1, sizeof(char)); if (!semanage_conf) return NULL; snprintf(semanage_conf, len + 1, "%s%s%s", semanage_root(), selinux_path(), SEMANAGE_CONF_FILE); if (stat(semanage_conf, &sb) != 0 && errno == ENOENT) { snprintf(semanage_conf, len + 1, "%s%s", selinux_path(), SEMANAGE_CONF_FILE); } return semanage_conf; } /**************** functions that create module store ***************/ /* Check that the semanage store exists. If 'create' is non-zero then * create the directories. Returns 0 if module store exists (either * already or just created), -1 if does not exist or could not be * read, or -2 if it could not create the store. */ int semanage_create_store(semanage_handle_t * sh, int create) { struct stat sb; const char *path = semanage_files[SEMANAGE_ROOT]; int fd; mode_t mask; if (stat(path, &sb) == -1) { if (errno == ENOENT && create) { mask = umask(0077); if (mkdir(path, S_IRWXU) == -1) { umask(mask); ERR(sh, "Could not create module store at %s.", path); return -2; } umask(mask); } else { if (create) ERR(sh, "Could not read from module store at %s.", path); return -1; } } else { if (!S_ISDIR(sb.st_mode)) { ERR(sh, "Module store at %s is not a directory.", path); return -1; } } path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL); if (stat(path, &sb) == -1) { if (errno == ENOENT && create) { mask = umask(0077); if (mkdir(path, S_IRWXU) == -1) { umask(mask); ERR(sh, "Could not create module store, active subdirectory at %s.", path); return -2; } umask(mask); } else { ERR(sh, "Could not read from module store, active subdirectory at %s.", path); return -1; } } else { if (!S_ISDIR(sb.st_mode)) { ERR(sh, "Module store active subdirectory at %s is not a directory.", path); return -1; } } path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES); if (stat(path, &sb) == -1) { if (errno == ENOENT && create) { mask = umask(0077); if (mkdir(path, S_IRWXU) == -1) { umask(mask); ERR(sh, "Could not create module store, active modules subdirectory at %s.", path); return -2; } umask(mask); } else { ERR(sh, "Could not read from module store, active modules subdirectory at %s.", path); return -1; } } else { if (!S_ISDIR(sb.st_mode)) { ERR(sh, "Module store active modules subdirectory at %s is not a directory.", path); return -1; } } path = semanage_files[SEMANAGE_READ_LOCK]; if (stat(path, &sb) == -1) { if (errno == ENOENT && create) { mask = umask(0077); if ((fd = creat(path, S_IRUSR | S_IWUSR)) == -1) { umask(mask); ERR(sh, "Could not create lock file at %s.", path); return -2; } umask(mask); close(fd); } else { ERR(sh, "Could not read lock file at %s.", path); return -1; } } else { if (!S_ISREG(sb.st_mode)) { ERR(sh, "Object at %s is not a lock file.", path); return -1; } } return 0; } /* returns <0 if the active store cannot be read or doesn't exist * 0 if the store exists but the lock file cannot be accessed * SEMANAGE_CAN_READ if the store can be read and the lock file used * SEMANAGE_CAN_WRITE if the modules directory and binary policy dir can be written to */ int semanage_store_access_check(void) { const char *path; int rc = -1; /* read access on active store */ path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL); if (access(path, R_OK | X_OK) != 0) goto out; /* we can read the active store meaning it is managed * so now we return 0 to indicate no error */ rc = 0; /* read access on lock file required for locking * write access necessary if the lock file does not exist */ path = semanage_files[SEMANAGE_READ_LOCK]; if (access(path, R_OK) != 0) { if (access(path, F_OK) == 0) { goto out; } path = semanage_files[SEMANAGE_ROOT]; if (access(path, R_OK | W_OK | X_OK) != 0) { goto out; } } /* everything needed for reading has been checked */ rc = SEMANAGE_CAN_READ; /* check the modules directory */ path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES); if (access(path, R_OK | W_OK | X_OK) != 0) goto out; rc = SEMANAGE_CAN_WRITE; out: return rc; } /********************* other I/O functions *********************/ /* Callback used by scandir() to select files. */ static int semanage_filename_select(const struct dirent *d) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) return 0; return 1; } /* Copies a file from src to dst. If dst already exists then * overwrite it. Returns 0 on success, -1 on error. */ int semanage_copy_file(const char *src, const char *dst, mode_t mode) { int in, out, retval = 0, amount_read, n, errsv = errno; char tmp[PATH_MAX]; char buf[4192]; mode_t mask; n = snprintf(tmp, PATH_MAX, "%s.tmp", dst); if (n < 0 || n >= PATH_MAX) return -1; if ((in = open(src, O_RDONLY)) == -1) { return -1; } if (!mode) mode = S_IRUSR | S_IWUSR; mask = umask(0); if ((out = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, mode)) == -1) { umask(mask); errsv = errno; close(in); retval = -1; goto out; } umask(mask); while (retval == 0 && (amount_read = read(in, buf, sizeof(buf))) > 0) { if (write(out, buf, amount_read) < 0) { errsv = errno; retval = -1; } } if (amount_read < 0) { errsv = errno; retval = -1; } close(in); if (close(out) < 0) { errsv = errno; retval = -1; } if (!retval && rename(tmp, dst) == -1) return -1; out: errno = errsv; return retval; } static int semanage_copy_dir_flags(const char *src, const char *dst, int flag); /* Copies all of the files from src to dst, recursing into * subdirectories. Returns 0 on success, -1 on error. */ static int semanage_copy_dir(const char *src, const char *dst) { return semanage_copy_dir_flags(src, dst, 1); } /* Copies all of the dirs from src to dst, recursing into * subdirectories. If flag == 1, then copy regular files as * well. Returns 0 on success, -1 on error. */ static int semanage_copy_dir_flags(const char *src, const char *dst, int flag) { int i, len = 0, retval = -1; struct stat sb; struct dirent **names = NULL; char path[PATH_MAX], path2[PATH_MAX]; mode_t mask; if ((len = scandir(src, &names, semanage_filename_select, NULL)) == -1) { fprintf(stderr, "Could not read the contents of %s: %s\n", src, strerror(errno)); return -1; } if (stat(dst, &sb) != 0) { mask = umask(0077); if (mkdir(dst, S_IRWXU) != 0) { umask(mask); fprintf(stderr, "Could not create %s: %s\n", dst, strerror(errno)); goto cleanup; } umask(mask); } for (i = 0; i < len; i++) { snprintf(path, sizeof(path), "%s/%s", src, names[i]->d_name); /* stat() to see if this entry is a file or not since * d_type isn't set properly on XFS */ if (stat(path, &sb)) { goto cleanup; } snprintf(path2, sizeof(path2), "%s/%s", dst, names[i]->d_name); if (S_ISDIR(sb.st_mode)) { mask = umask(0077); if (mkdir(path2, 0700) == -1 || semanage_copy_dir_flags(path, path2, flag) == -1) { umask(mask); goto cleanup; } umask(mask); } else if (S_ISREG(sb.st_mode) && flag == 1) { mask = umask(0077); if (semanage_copy_file(path, path2, sb.st_mode) < 0) { umask(mask); goto cleanup; } umask(mask); } } retval = 0; cleanup: for (i = 0; names != NULL && i < len; i++) { free(names[i]); } free(names); return retval; } /* Recursively removes the contents of a directory along with the * directory itself. Returns 0 on success, non-zero on error. */ int semanage_remove_directory(const char *path) { struct dirent **namelist = NULL; int num_entries, i; if ((num_entries = scandir(path, &namelist, semanage_filename_select, NULL)) == -1) { return -1; } for (i = 0; i < num_entries; i++) { char s[PATH_MAX]; struct stat buf; snprintf(s, sizeof(s), "%s/%s", path, namelist[i]->d_name); if (stat(s, &buf) == -1) { return -2; } if (S_ISDIR(buf.st_mode)) { int retval; if ((retval = semanage_remove_directory(s)) != 0) { return retval; } } else { if (remove(s) == -1) { return -3; } } free(namelist[i]); } free(namelist); if (rmdir(path) == -1) { return -4; } return 0; } int semanage_mkpath(semanage_handle_t *sh, const char *path) { char fn[PATH_MAX]; char *c; int rc = 0; if (strlen(path) >= PATH_MAX) { return -1; } for (c = strcpy(fn, path) + 1; *c != '\0'; c++) { if (*c != '/') { continue; } *c = '\0'; rc = semanage_mkdir(sh, fn); if (rc < 0) { goto cleanup; } *c = '/'; } rc = semanage_mkdir(sh, fn); cleanup: return rc; } int semanage_mkdir(semanage_handle_t *sh, const char *path) { int status = 0; struct stat sb; mode_t mask; /* check if directory already exists */ if (stat(path, &sb) != 0) { /* make the modules directory */ mask = umask(0077); if (mkdir(path, S_IRWXU) != 0) { umask(mask); ERR(sh, "Cannot make directory at %s", path); status = -1; goto cleanup; } umask(mask); } else { /* check that it really is a directory */ if (!S_ISDIR(sb.st_mode)) { ERR(sh, "Directory path taken by non-directory file at %s.", path); status = -1; goto cleanup; } } cleanup: return status; } /********************* sandbox management routines *********************/ /* Creates a sandbox for a single client. Returns 0 if a * sandbox was created, -1 on error. */ int semanage_make_sandbox(semanage_handle_t * sh) { const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL); struct stat buf; int errsv; mode_t mask; if (stat(sandbox, &buf) == -1) { if (errno != ENOENT) { ERR(sh, "Error scanning directory %s.", sandbox); return -1; } errno = 0; } else { /* remove the old sandbox */ if (semanage_remove_directory(sandbox) != 0) { ERR(sh, "Error removing old sandbox directory %s.", sandbox); return -1; } } mask = umask(0077); if (mkdir(sandbox, S_IRWXU) == -1 || semanage_copy_dir(semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL), sandbox) == -1) { umask(mask); ERR(sh, "Could not copy files to sandbox %s.", sandbox); goto cleanup; } umask(mask); return 0; cleanup: errsv = errno; semanage_remove_directory(sandbox); errno = errsv; return -1; } /* Create final temporary space. Returns -1 on error 0 on success. */ int semanage_make_final(semanage_handle_t *sh) { int status = 0; int ret = 0; char fn[PATH_MAX]; /* Create tmp dir if it does not exist. */ ret = snprintf(fn, sizeof(fn), "%s%s%s", semanage_root(), sh->conf->store_root_path, semanage_final_prefix[SEMANAGE_FINAL_TMP]); if (ret < 0 || ret >= (int)sizeof(fn)) { ERR(sh, "Unable to compose the final tmp path."); status = -1; goto cleanup; } ret = semanage_mkdir(sh, fn); if (ret != 0) { ERR(sh, "Unable to create temporary directory for final files at %s", fn); status = -1; goto cleanup; } /* Delete store specific dir if it exists. */ ret = semanage_remove_directory( semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FINAL_TOPLEVEL)); if (ret < -1) { status = -1; goto cleanup; } // Build final directory structure int i; for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) { if (strlen(semanage_final_path(SEMANAGE_FINAL_TMP, i)) >= sizeof(fn)) { ERR(sh, "Unable to compose the final paths."); status = -1; goto cleanup; } strcpy(fn, semanage_final_path(SEMANAGE_FINAL_TMP, i)); ret = semanage_mkpath(sh, dirname(fn)); if (ret < 0) { status = -1; goto cleanup; } } cleanup: return status; } /* qsort comparison function for semanage_get_active_modules. */ static int semanage_get_active_modules_cmp(const void *a, const void *b) { semanage_module_info_t *aa = (semanage_module_info_t *)a; semanage_module_info_t *bb = (semanage_module_info_t *)b; return strcmp(aa->name, bb->name); } int semanage_get_cil_paths(semanage_handle_t * sh, semanage_module_info_t *modinfos, int num_modinfos, char *** filenames) { char path[PATH_MAX]; char **names = NULL; int ret; int status = 0; int i = 0; names = calloc(num_modinfos, sizeof(*names)); if (names == NULL) { ERR(sh, "Error allocating space for filenames."); return -1; } for (i = 0; i < num_modinfos; i++) { ret = semanage_module_get_path( sh, &modinfos[i], SEMANAGE_MODULE_PATH_CIL, path, sizeof(path)); if (ret != 0) { status = -1; goto cleanup; } names[i] = strdup(path); if (names[i] == NULL) { status = -1; goto cleanup; } } cleanup: if (status != 0) { for (i = 0; i < num_modinfos; i++) { free(names[i]); } free(names); } else { *filenames = names; } return status; } /* Scans the modules directory for the current semanage handler. This * might be the active directory or sandbox, depending upon if the * handler has a transaction lock. Allocates and fills in *modinfos * with an array of module infos; length of array is stored in * *num_modules. The caller is responsible for free()ing *modinfos and its * individual elements. Upon success returns 0, -1 on error. */ int semanage_get_active_modules(semanage_handle_t * sh, semanage_module_info_t ** modinfo, int *num_modules) { assert(sh); assert(modinfo); assert(num_modules); *modinfo = NULL; *num_modules = 0; int status = 0; int ret = 0; int i = 0; int j = 0; semanage_list_t *list = NULL; semanage_list_t *found = NULL; semanage_module_info_t *all_modinfos = NULL; int all_modinfos_len = 0; void *tmp = NULL; /* get all modules */ ret = semanage_module_list_all(sh, &all_modinfos, &all_modinfos_len); if (ret != 0) { status = -1; goto cleanup; } if (all_modinfos_len == 0) { goto cleanup; } /* allocate enough for worst case */ (*modinfo) = calloc(all_modinfos_len, sizeof(**modinfo)); if ((*modinfo) == NULL) { ERR(sh, "Error allocating space for module information."); status = -1; goto cleanup; } /* for each highest priority, enabled module get its path */ semanage_list_destroy(&list); j = 0; for (i = 0; i < all_modinfos_len; i++) { /* check if enabled */ if (all_modinfos[i].enabled != 1) continue; /* check if we've seen this before (i.e. highest priority) */ found = semanage_list_find(list, all_modinfos[i].name); if (found == NULL) { ret = semanage_list_push(&list, all_modinfos[i].name); if (ret != 0) { ERR(sh, "Failed to add module name to list of known names."); status = -1; goto cleanup; } } else continue; if (semanage_module_info_clone(sh, &all_modinfos[i], &(*modinfo)[j]) != 0) { status = -1; goto cleanup; } j += 1; } *num_modules = j; if (j == 0) { free(*modinfo); *modinfo = NULL; goto cleanup; } /* realloc the array to its min size */ tmp = realloc(*modinfo, j * sizeof(**modinfo)); if (tmp == NULL) { ERR(sh, "Error allocating space for filenames."); status = -1; goto cleanup; } *modinfo = tmp; /* sort array on module name */ qsort(*modinfo, *num_modules, sizeof(**modinfo), semanage_get_active_modules_cmp); cleanup: semanage_list_destroy(&list); for (i = 0; i < all_modinfos_len; i++) { semanage_module_info_destroy(sh, &all_modinfos[i]); } free(all_modinfos); if (status != 0) { for (i = 0; i < j; i++) { semanage_module_info_destroy(sh, &(*modinfo)[i]); } free(*modinfo); } return status; } /******************* routines that run external programs *******************/ /* Appends a single character to a string. Returns a pointer to the * realloc()ated string. If out of memory return NULL; original * string will remain untouched. */ static char *append(char *s, char c) { size_t len = (s == NULL ? 0 : strlen(s)); char *new_s = realloc(s, len + 2); if (new_s == NULL) { return NULL; } s = new_s; s[len] = c; s[len + 1] = '\0'; return s; } /* Append string 't' to string 's', realloc()ating 's' as needed. 't' * may be safely free()d afterwards. Returns a pointer to the * realloc()ated 's'. If out of memory return NULL; original strings * will remain untouched. */ static char *append_str(char *s, const char *t) { size_t s_len = (s == NULL ? 0 : strlen(s)); size_t t_len; char *new_s; if (t == NULL) { return s; } t_len = strlen(t); new_s = realloc(s, s_len + t_len + 1); if (new_s == NULL) { return NULL; } s = new_s; memcpy(s + s_len, t, t_len); s[s_len + t_len] = '\0'; return s; } /* * Append an argument string to an argument vector. Replaces the * argument pointer passed in. Returns -1 on error. Increments * 'num_args' on success. */ static int append_arg(char ***argv, int *num_args, const char *arg) { char **a; a = realloc(*argv, sizeof(**argv) * (*num_args + 1)); if (a == NULL) return -1; *argv = a; a[*num_args] = NULL; if (arg) { a[*num_args] = strdup(arg); if (!a[*num_args]) return -1; } (*num_args)++; return 0; } /* free()s all strings within a null-terminated argument vector, as * well as the pointer itself. */ static void free_argv(char **argv) { int i; for (i = 0; argv != NULL && argv[i] != NULL; i++) { free(argv[i]); } free(argv); } /* Take an argument string and split and place into an argument * vector. Respect normal quoting, double-quoting, and backslash * conventions. Perform substitutions on $@ and $< symbols. Returns * a NULL-terminated argument vector; caller is responsible for * free()ing the vector and its elements. */ static char **split_args(const char *arg0, char *arg_string, const char *new_name, const char *old_name) { char **argv = NULL, *s, *arg = NULL, *targ; int num_args = 0, in_quote = 0, in_dquote = 0, rc; rc = append_arg(&argv, &num_args, arg0); if (rc) goto cleanup; s = arg_string; /* parse the argument string one character at a time, * repsecting quotes and other special characters */ while (s != NULL && *s != '\0') { switch (*s) { case '\\':{ if (*(s + 1) == '\0') { targ = append(arg, '\\'); if (targ == NULL) goto cleanup; arg = targ; } else { targ = append(arg, *(s + 1)); if (targ == NULL) goto cleanup; arg = targ; s++; } break; } case '\'':{ if (in_dquote) { targ = append(arg, *s); if (targ == NULL) goto cleanup; arg = targ; } else if (in_quote) { in_quote = 0; } else { in_quote = 1; targ = append(arg, '\0'); if (targ == NULL) goto cleanup; arg = targ; } break; } case '\"':{ if (in_quote) { targ = append(arg, *s); if (targ == NULL) goto cleanup; arg = targ; } else if (in_dquote) { in_dquote = 0; } else { in_dquote = 1; targ = append(arg, '\0'); if (targ == NULL) goto cleanup; arg = targ; } break; } case '$':{ switch (*(s + 1)) { case '@':{ targ = append_str(arg, new_name); if (targ == NULL) goto cleanup; arg = targ; s++; break; } case '<':{ targ = append_str(arg, old_name); if (targ == NULL) goto cleanup; arg = targ; s++; break; } default:{ targ = append(arg, *s); if (targ == NULL) goto cleanup; arg = targ; } } break; } default:{ if (isspace(*s) && !in_quote && !in_dquote) { if (arg != NULL) { rc = append_arg(&argv, &num_args, arg); if (rc) goto cleanup; free(arg); arg = NULL; } } else { if ((targ = append(arg, *s)) == NULL) { goto cleanup; } else { arg = targ; } } } } s++; } if (arg != NULL) { rc = append_arg(&argv, &num_args, arg); if (rc) goto cleanup; free(arg); arg = NULL; } /* explicitly add a NULL at the end */ rc = append_arg(&argv, &num_args, NULL); if (rc) goto cleanup; return argv; cleanup: free_argv(argv); free(arg); return NULL; } /* Take the arguments given in v->args and expand any $ macros within. * Split the arguments into different strings (argv). Next fork and * execute the process. BE SURE THAT ALL FILE DESCRIPTORS ARE SET TO * CLOSE-ON-EXEC. Take the return value of the child process and * return it, -1 on error. */ static int semanage_exec_prog(semanage_handle_t * sh, external_prog_t * e, const char *new_name, const char *old_name) { char **argv; pid_t forkval; int status = 0; argv = split_args(e->path, e->args, new_name, old_name); if (argv == NULL) { ERR(sh, "Out of memory!"); return -1; } /* no need to use pthread_atfork() -- child will not be using * any mutexes. */ forkval = vfork(); if (forkval == 0) { /* child process. file descriptors will be closed * because they were set as close-on-exec. */ execve(e->path, argv, NULL); _exit(EXIT_FAILURE); /* if execve() failed */ } free_argv(argv); if (forkval == -1) { ERR(sh, "Error while forking process."); return -1; } /* parent process. wait for child to finish */ if (waitpid(forkval, &status, 0) == -1 || !WIFEXITED(status)) { ERR(sh, "Child process %s did not exit cleanly.", e->path); return -1; } return WEXITSTATUS(status); } /* reloads the policy pointed to by the handle, used locally by install * and exported for user reload requests */ int semanage_reload_policy(semanage_handle_t * sh) { int r = 0; if (!sh) return -1; if ((r = semanage_exec_prog(sh, sh->conf->load_policy, "", "")) != 0) { ERR(sh, "load_policy returned error code %d.", r); } return r; } hidden_def(semanage_reload_policy) /* This expands the file_context.tmpl file to file_context and homedirs.template */ int semanage_split_fc(semanage_handle_t * sh) { FILE *file_con = NULL; int fc = -1, hd = -1, retval = -1; char buf[PATH_MAX] = { 0 }; /* I use fopen here instead of open so that I can use fgets which only reads a single line */ file_con = fopen(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL), "r"); if (!file_con) { ERR(sh, "Could not open %s for reading.", semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL)); goto cleanup; } fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fc < 0) { ERR(sh, "Could not open %s for writing.", semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC)); goto cleanup; } hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (hd < 0) { ERR(sh, "Could not open %s for writing.", semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL)); goto cleanup; } while (fgets_unlocked(buf, PATH_MAX, file_con)) { if (!strncmp(buf, "HOME_DIR", 8) || !strncmp(buf, "HOME_ROOT", 9) || strstr(buf, "ROLE") || strstr(buf, "USER")) { /* This contains one of the template variables, write it to homedir.template */ if (write(hd, buf, strlen(buf)) < 0) { ERR(sh, "Write to %s failed.", semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL)); goto cleanup; } } else { if (write(fc, buf, strlen(buf)) < 0) { ERR(sh, "Write to %s failed.", semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC)); goto cleanup; } } } retval = 0; cleanup: if (file_con) fclose(file_con); if (fc >= 0) close(fc); if (hd >= 0) close(hd); return retval; } static int sefcontext_compile(semanage_handle_t * sh, const char *path) { int r; struct stat sb; if (stat(path, &sb) < 0) { if (errno != ENOENT) { ERR(sh, "Unable to access %s: %s\n", path, strerror(errno)); return -1; } return 0; } if ((r = semanage_exec_prog(sh, sh->conf->sefcontext_compile, path, "")) != 0) { ERR(sh, "sefcontext_compile returned error code %d. Compiling %s", r, path); return -1; } return 0; } static int semanage_validate_and_compile_fcontexts(semanage_handle_t * sh) { int status = -1; if (sh->do_check_contexts) { int ret; ret = semanage_exec_prog( sh, sh->conf->setfiles, semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL), semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC)); if (ret != 0) { ERR(sh, "setfiles returned error code %d.", ret); goto cleanup; } } if (sefcontext_compile(sh, semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC)) != 0) { goto cleanup; } if (sefcontext_compile(sh, semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL)) != 0) { goto cleanup; } if (sefcontext_compile(sh, semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS)) != 0) { goto cleanup; } status = 0; cleanup: return status; } /* Load the contexts of the final tmp into the final selinux directory. * Return 0 on success, -3 on error. */ static int semanage_install_final_tmp(semanage_handle_t * sh) { int status = -3; int ret = 0; int i = 0; const char *src = NULL; const char *dst = NULL; struct stat sb; char fn[PATH_MAX]; /* For each of the final files install it if it exists. * i = 1 to avoid copying the top level directory. */ for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) { src = semanage_final_path(SEMANAGE_FINAL_TMP, i); dst = semanage_final_path(SEMANAGE_FINAL_SELINUX, i); /* skip file if src doesn't exist */ if (stat(src, &sb) != 0) continue; /* skip genhomedircon if configured */ if (sh->conf->disable_genhomedircon && i == SEMANAGE_FC_HOMEDIRS) continue; if (strlen(dst) >= sizeof(fn)) { ERR(sh, "Unable to compose the final paths."); status = -1; goto cleanup; } strcpy(fn, dst); ret = semanage_mkpath(sh, dirname(fn)); if (ret < 0) { goto cleanup; } ret = semanage_copy_file(src, dst, sh->conf->file_mode); if (ret < 0) { ERR(sh, "Could not copy %s to %s.", src, dst); goto cleanup; } } if (!sh->do_reload) goto skip_reload; /* This stats what libselinux says the active store is (according to config) * and what we are installing to, to decide if they are the same store. If * they are not then we do not reload policy. */ const char *really_active_store = selinux_policy_root(); struct stat astore; struct stat istore; const char *storepath = semanage_final_path(SEMANAGE_FINAL_SELINUX, SEMANAGE_FINAL_TOPLEVEL); if (stat(really_active_store, &astore) == 0) { if (stat(storepath, &istore)) { ERR(sh, "Could not stat store path %s.", storepath); goto cleanup; } if (!(astore.st_ino == istore.st_ino && astore.st_dev == istore.st_dev)) { /* They are not the same store */ goto skip_reload; } } else if (errno == ENOENT && strcmp(really_active_store, storepath) != 0) { errno = 0; goto skip_reload; } if (semanage_reload_policy(sh)) { goto cleanup; } skip_reload: status = 0; cleanup: return status; } /* Prepare the sandbox to be installed by making a backup of the * current active directory. Then copy the sandbox to the active * directory. Return the new commit number on success, negative * values on error. */ static int semanage_commit_sandbox(semanage_handle_t * sh) { int commit_number, fd, retval; char write_buf[32]; const char *commit_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE); ssize_t amount_written; const char *active = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL); const char *backup = semanage_path(SEMANAGE_PREVIOUS, SEMANAGE_TOPLEVEL); const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL); struct stat buf; /* update the commit number */ if ((commit_number = semanage_direct_get_serial(sh)) < 0) { return -1; } commit_number++; memset(write_buf, 0, sizeof(write_buf)); snprintf(write_buf, sizeof(write_buf), "%d", commit_number); if ((fd = open(commit_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) { ERR(sh, "Could not open commit number file %s for writing.", commit_filename); return -1; } amount_written = write(fd, write_buf, sizeof(write_buf)); if (amount_written == -1) { ERR(sh, "Error while writing commit number to %s.", commit_filename); close(fd); return -1; } close(fd); retval = commit_number; if (semanage_get_active_lock(sh) < 0) { return -1; } /* make the backup of the current active directory */ if (stat(backup, &buf) == 0) { if (S_ISDIR(buf.st_mode) && semanage_remove_directory(backup) != 0) { ERR(sh, "Could not remove previous backup %s.", backup); retval = -1; goto cleanup; } } else if (errno != ENOENT) { ERR(sh, "Could not stat directory %s.", backup); retval = -1; goto cleanup; } if (rename(active, backup) == -1) { ERR(sh, "Error while renaming %s to %s.", active, backup); retval = -1; goto cleanup; } /* clean up some files from the sandbox before install */ /* remove homedir_template from sandbox */ if (rename(sandbox, active) == -1) { ERR(sh, "Error while renaming %s to %s.", sandbox, active); /* note that if an error occurs during the next * function then the store will be left in an * inconsistent state */ if (rename(backup, active) < 0) ERR(sh, "Error while renaming %s back to %s.", backup, active); retval = -1; goto cleanup; } if (semanage_install_final_tmp(sh) != 0) { /* note that if an error occurs during the next three * function then the store will be left in an * inconsistent state */ int errsv = errno; if (rename(active, sandbox) < 0) ERR(sh, "Error while renaming %s back to %s.", active, sandbox); else if (rename(backup, active) < 0) ERR(sh, "Error while renaming %s back to %s.", backup, active); else semanage_install_final_tmp(sh); errno = errsv; retval = -1; goto cleanup; } if (!sh->conf->save_previous) { int errsv = errno; if (semanage_remove_directory(backup) != 0) { ERR(sh, "Could not delete previous directory %s.", backup); retval = -1; goto cleanup; } errno = errsv; } cleanup: semanage_release_active_lock(sh); return retval; } /* Takes the kernel policy in a sandbox, move it to the active * directory, copy it to the binary policy path, then load it. Upon * error move the active directory back to the sandbox. This function * should be placed within a mutex lock to ensure that it runs * atomically. Returns commit number on success, -1 on error. */ int semanage_install_sandbox(semanage_handle_t * sh) { int retval = -1, commit_num = -1; if (sh->conf->load_policy == NULL) { ERR(sh, "No load_policy program specified in configuration file."); goto cleanup; } if (sh->conf->setfiles == NULL) { ERR(sh, "No setfiles program specified in configuration file."); goto cleanup; } if (sh->conf->sefcontext_compile == NULL) { ERR(sh, "No sefcontext_compile program specified in configuration file."); goto cleanup; } if (semanage_validate_and_compile_fcontexts(sh) < 0) goto cleanup; if ((commit_num = semanage_commit_sandbox(sh)) < 0) { retval = commit_num; goto cleanup; } retval = commit_num; cleanup: return retval; } /********************* functions that manipulate lock *********************/ static int semanage_get_lock(semanage_handle_t * sh, const char *lock_name, const char *lock_file) { int fd; struct timeval origtime, curtime; int got_lock = 0; if ((fd = open(lock_file, O_RDONLY)) == -1) { if ((fd = open(lock_file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) { ERR(sh, "Could not open direct %s at %s.", lock_name, lock_file); return -1; } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { ERR(sh, "Could not set close-on-exec for %s at %s.", lock_name, lock_file); close(fd); return -1; } if (sh->timeout == 0) { /* return immediately */ origtime.tv_sec = 0; } else { origtime.tv_sec = sh->timeout; } origtime.tv_usec = 0; do { curtime.tv_sec = 1; curtime.tv_usec = 0; if (flock(fd, LOCK_EX | LOCK_NB) == 0) { got_lock = 1; break; } else if (errno != EAGAIN) { ERR(sh, "Error obtaining direct %s at %s.", lock_name, lock_file); close(fd); return -1; } if (origtime.tv_sec > 0 || sh->timeout == -1) { if (select(0, NULL, NULL, NULL, &curtime) == -1) { if (errno == EINTR) { continue; } ERR(sh, "Error while waiting to get direct %s at %s.", lock_name, lock_file); close(fd); return -1; } origtime.tv_sec--; } } while (origtime.tv_sec > 0 || sh->timeout == -1); if (!got_lock) { ERR(sh, "Could not get direct %s at %s.", lock_name, lock_file); close(fd); return -1; } return fd; } /* Locking for the module store for transactions. This is very basic * locking of the module store and doesn't do anything if the module * store is being manipulated with a program not using this library * (but the policy should prevent that). Returns 0 on success, -1 if * it could not obtain a lock. */ int semanage_get_trans_lock(semanage_handle_t * sh) { const char *lock_file = semanage_files[SEMANAGE_TRANS_LOCK]; if (sh->u.direct.translock_file_fd >= 0) return 0; sh->u.direct.translock_file_fd = semanage_get_lock(sh, "transaction lock", lock_file); if (sh->u.direct.translock_file_fd >= 0) { return 0; } else { return -1; } } /* Locking for the module store for active store reading; this also includes * the file containing the commit number. This is very basic locking * of the module store and doesn't do anything if the module store is * being manipulated with a program not using this library (but the * policy should prevent that). Returns 0 on success, -1 if it could * not obtain a lock. */ int semanage_get_active_lock(semanage_handle_t * sh) { const char *lock_file = semanage_files[SEMANAGE_READ_LOCK]; if (sh->u.direct.activelock_file_fd >= 0) return 0; sh->u.direct.activelock_file_fd = semanage_get_lock(sh, "read lock", lock_file); if (sh->u.direct.activelock_file_fd >= 0) { return 0; } else { return -1; } } /* Releases the transaction lock. Does nothing if there was not one already * there. */ void semanage_release_trans_lock(semanage_handle_t * sh) { int errsv = errno; if (sh->u.direct.translock_file_fd >= 0) { flock(sh->u.direct.translock_file_fd, LOCK_UN); close(sh->u.direct.translock_file_fd); sh->u.direct.translock_file_fd = -1; } errno = errsv; } /* Releases the read lock. Does nothing if there was not one already * there. */ void semanage_release_active_lock(semanage_handle_t * sh) { int errsv = errno; if (sh->u.direct.activelock_file_fd >= 0) { flock(sh->u.direct.activelock_file_fd, LOCK_UN); close(sh->u.direct.activelock_file_fd); sh->u.direct.activelock_file_fd = -1; } errno = errsv; } /* Read the current commit number from the commit number file which * the handle is pointing, resetting the file pointer afterwards. * Return it (a non-negative number), or -1 on error. */ int semanage_direct_get_serial(semanage_handle_t * sh) { char buf[32]; int fd, commit_number; ssize_t amount_read; const char *commit_filename; memset(buf, 0, sizeof(buf)); if (sh->is_in_transaction) { commit_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE); } else { commit_filename = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_COMMIT_NUM_FILE); } if ((fd = open(commit_filename, O_RDONLY)) == -1) { if (errno == ENOENT) { /* the commit number file does not exist yet, * so assume that the number is 0 */ errno = 0; return 0; } else { ERR(sh, "Could not open commit number file %s.", commit_filename); return -1; } } amount_read = read(fd, buf, sizeof(buf)); if (amount_read == -1) { ERR(sh, "Error while reading commit number from %s.", commit_filename); commit_number = -1; } else if (sscanf(buf, "%d", &commit_number) != 1) { /* if nothing was read, assume that the commit number is 0 */ commit_number = 0; } else if (commit_number < 0) { /* read file ought never have negative values */ ERR(sh, "Commit number file %s is corrupted; it should only contain a non-negative integer.", commit_filename); commit_number = -1; } close(fd); return commit_number; } /* HIGHER LEVEL COMMIT FUNCTIONS */ int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles) { int retval = 0; FILE *fp; ssize_t size; char *data = NULL; char *filename; int i; for (i = 0; i < numfiles; i++) { filename = filenames[i]; if ((fp = fopen(filename, "rb")) == NULL) { ERR(sh, "Could not open module file %s for reading.", filename); goto cleanup; } if ((size = bunzip(sh, fp, &data)) <= 0) { rewind(fp); __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fseek(fp, 0, SEEK_END) != 0) { ERR(sh, "Failed to determine size of file %s.", filename); goto cleanup; } size = ftell(fp); rewind(fp); data = malloc(size); if (fread(data, size, 1, fp) != 1) { ERR(sh, "Failed to read file %s.", filename); goto cleanup; } } fclose(fp); fp = NULL; retval = cil_add_file(cildb, filename, data, size); if (retval != SEPOL_OK) { ERR(sh, "Error while reading from file %s.", filename); goto cleanup; } free(data); data = NULL; } return retval; cleanup: if (fp != NULL) { fclose(fp); } free(data); return -1; } /* * Expands the policy contained within *base */ /** * Read the policy from the sandbox (linked or kernel) */ int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in, enum semanage_sandbox_defs file) { int retval = STATUS_ERR; const char *kernel_filename = NULL; struct sepol_policy_file *pf = NULL; FILE *infile = NULL; if ((kernel_filename = semanage_path(SEMANAGE_ACTIVE, file)) == NULL) { goto cleanup; } if ((infile = fopen(kernel_filename, "r")) == NULL) { ERR(sh, "Could not open kernel policy %s for reading.", kernel_filename); goto cleanup; } __fsetlocking(infile, FSETLOCKING_BYCALLER); if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); goto cleanup; } sepol_policy_file_set_fp(pf, infile); sepol_policy_file_set_handle(pf, sh->sepolh); if (sepol_policydb_read(in, pf) == -1) { ERR(sh, "Error while reading kernel policy from %s.", kernel_filename); goto cleanup; } retval = STATUS_SUCCESS; cleanup: if (infile != NULL) { fclose(infile); } sepol_policy_file_free(pf); return retval; } /** * Writes the policy to the sandbox (linked or kernel) */ int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out, enum semanage_sandbox_defs file) { int retval = STATUS_ERR; const char *kernel_filename = NULL; struct sepol_policy_file *pf = NULL; FILE *outfile = NULL; mode_t mask = umask(0077); if ((kernel_filename = semanage_path(SEMANAGE_TMP, file)) == NULL) { goto cleanup; } if ((outfile = fopen(kernel_filename, "wb")) == NULL) { ERR(sh, "Could not open kernel policy %s for writing.", kernel_filename); goto cleanup; } __fsetlocking(outfile, FSETLOCKING_BYCALLER); if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); goto cleanup; } sepol_policy_file_set_fp(pf, outfile); sepol_policy_file_set_handle(pf, sh->sepolh); if (sepol_policydb_write(out, pf) == -1) { ERR(sh, "Error while writing kernel policy to %s.", kernel_filename); goto cleanup; } retval = STATUS_SUCCESS; cleanup: if (outfile != NULL) { fclose(outfile); } umask(mask); sepol_policy_file_free(pf); return retval; } /* Execute the module verification programs for each source module. * Returns 0 if every verifier returned success, -1 on error. */ int semanage_verify_modules(semanage_handle_t * sh, char **module_filenames, int num_modules) { int i, retval; semanage_conf_t *conf = sh->conf; if (conf->mod_prog == NULL) { return 0; } for (i = 0; i < num_modules; i++) { char *module = module_filenames[i]; external_prog_t *e; for (e = conf->mod_prog; e != NULL; e = e->next) { if ((retval = semanage_exec_prog(sh, e, module, "$<")) != 0) { return -1; } } } return 0; } /* Execute the linker verification programs for the linked (but not * expanded) base. Returns 0 if every verifier returned success, -1 * on error. */ int semanage_verify_linked(semanage_handle_t * sh) { external_prog_t *e; semanage_conf_t *conf = sh->conf; const char *linked_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED); int retval = -1; if (conf->linked_prog == NULL) { return 0; } for (e = conf->linked_prog; e != NULL; e = e->next) { if (semanage_exec_prog(sh, e, linked_filename, "$<") != 0) { goto cleanup; } } retval = 0; cleanup: return retval; } /* Execute each of the kernel verification programs. Returns 0 if * every verifier returned success, -1 on error. */ int semanage_verify_kernel(semanage_handle_t * sh) { int retval = -1; const char *kernel_filename = semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL); semanage_conf_t *conf = sh->conf; external_prog_t *e; if (conf->kernel_prog == NULL) { return 0; } for (e = conf->kernel_prog; e != NULL; e = e->next) { if (semanage_exec_prog(sh, e, kernel_filename, "$<") != 0) { goto cleanup; } } retval = 0; cleanup: return retval; } /********************* functions that sort file contexts *********************/ /* Free the given node. */ static void semanage_fc_node_destroy(semanage_file_context_node_t * x) { free(x->path); free(x->file_type); free(x->context); free(x); } /* Free the linked list of nodes starting at the given node. */ static void semanage_fc_node_list_destroy(semanage_file_context_node_t * x) { semanage_file_context_node_t *temp; while (x) { temp = x; x = x->next; semanage_fc_node_destroy(temp); } } /* Free the linked list of buckets (and their node lists) * starting at the given bucket. */ static void semanage_fc_bucket_list_destroy(semanage_file_context_bucket_t * x) { semanage_file_context_bucket_t *temp; while (x) { temp = x; x = x->next; semanage_fc_node_list_destroy(temp->data); free(temp); } } /* Compares two file contexts' regular expressions and returns: * -1 if a is less specific than b * 0 if a and be are equally specific * 1 if a is more specific than b * The comparison is based on the following heuristics, * in order from most important to least important, given a and b: * If a is a regular expression and b is not, * -> a is less specific than b. * If a's stem length is shorter than b's stem length, * -> a is less specific than b. * If a's string length is shorter than b's string length, * -> a is less specific than b. * If a does not have a specified type and b does not, * -> a is less specific than b. * FIXME: These heuristics are imperfect, but good enough for * now. A proper comparison would determine which (if either) * regular expression is a subset of the other. */ static int semanage_fc_compare(semanage_file_context_node_t * a, semanage_file_context_node_t * b) { int a_has_meta = (a->meta >= 0); int b_has_meta = (b->meta >= 0); /* Check to see if either a or b are regexes * and the other isn't. */ if (a_has_meta && !b_has_meta) return -1; if (b_has_meta && !a_has_meta) return 1; /* Check to see if either a or b have a shorter stem * length than the other. */ if (a->meta < b->meta) return -1; if (b->meta < a->meta) return 1; /* Check to see if either a or b have a shorter string * length than the other. */ if (a->effective_len < b->effective_len) return -1; if (b->effective_len < a->effective_len) return 1; /* Check to see if either a or b has a specified type * and the other doesn't. */ if (!a->file_type && b->file_type) return -1; if (!b->file_type && a->file_type) return 1; /* If none of the above conditions were satisfied, * then a and b are equally specific. */ return 0; } /* Merges two sorted file context linked lists into a single sorted one. * The left list is assumed to represent nodes that came first in the original ordering. * The final sorted list is returned. */ static semanage_file_context_node_t * semanage_fc_merge(semanage_file_context_node_t * left, semanage_file_context_node_t * right) { semanage_file_context_node_t *head; semanage_file_context_node_t *current; semanage_file_context_node_t *tail; if (!left) return right; if (!right) return left; if (semanage_fc_compare(left, right) == 1) { head = tail = right; right = right->next; } else { head = tail = left; left = left->next; } while (left && right) { /* if left was more specific than right, * insert right before left. Otherwise leave order alone. */ if (semanage_fc_compare(left, right) == 1) { current = right; right = right->next; } else { current = left; left = left->next; } tail = tail->next = current; } tail->next = (left != NULL) ? left : right; return head; } /* Sorts file contexts from least specific to most specific. * A bucket linked list is passed in. Upon completion, * there is only one bucket (pointed to by master) that * contains a linked list of all the file contexts in sorted order. * Explanation of the algorithm: * This is a stable implementation of an iterative merge sort. * Each bucket initially has a linked list of file contexts * that are 1 node long. * Each pass, buckets (and the nodes they contain) are merged * two at time. * Buckets are merged until there is only one bucket left, * containing the list of file contexts, sorted. */ static void semanage_fc_merge_sort(semanage_file_context_bucket_t * master) { semanage_file_context_bucket_t *current; semanage_file_context_bucket_t *temp; /* Loop until master is the only bucket left. * When we stop master contains the sorted list. */ while (master->next) { current = master; /* Merge buckets two-by-two. * If there is an odd number of buckets, the last * bucket will be left alone, which corresponds * to the operation of merging it with an empty bucket. */ while (current) { if (current->next) { current->data = semanage_fc_merge(current->data, current->next->data); temp = current->next; current->next = current->next->next; /* Free the (now empty) second bucket. * (This does not touch the node list * in the bucket because it has been * shifted over to the first bucket. */ free(temp); } current = current->next; } } } /* Compute the location of the first regular expression * meta character in the path of the given node, if it exists. * On return: * fc_node->meta = position of meta character, if it exists * (-1 corresponds to no character) */ static void semanage_fc_find_meta(semanage_file_context_node_t * fc_node) { int c = 0; int escape_chars = 0; fc_node->meta = -1; /* Note: this while loop has been adapted from * spec_hasMetaChars in matchpathcon.c from * libselinux-1.22. */ while (fc_node->path[c] != '\0') { switch (fc_node->path[c]) { case '.': case '^': case '$': case '?': case '*': case '+': case '|': case '[': case '(': case '{': fc_node->meta = c - escape_chars; return; case '\\': /* If an escape character is found, * skip the next character. */ c++; escape_chars++; break; } c++; } } /* Replicates strchr, but limits search to buf_len characters. */ static char *semanage_strnchr(const char *buf, size_t buf_len, char c) { size_t idx = 0; if (buf == NULL) return NULL; if (buf_len <= 0) return NULL; while (idx < buf_len) { if (buf[idx] == c) return (char *)buf + idx; idx++; } return NULL; } /* Returns a pointer to the end of line character in the given buffer. * Used in the context of a file context char buffer that we will be * parsing and sorting. */ static char *semanage_get_line_end(const char *buf, size_t buf_len) { char *line_end = NULL; if (buf == NULL) return NULL; if (buf_len <= 0) return NULL; line_end = semanage_strnchr(buf, buf_len, '\n'); if (!line_end) line_end = semanage_strnchr(buf, buf_len, '\r'); if (!line_end) line_end = semanage_strnchr(buf, buf_len, EOF); return line_end; } /* Entry function for sorting a set of file context lines. * Returns 0 on success, -1 on failure. * Allocates a buffer pointed to by sorted_buf that contains the sorted lines. * sorted_buf_len is set to the size of this buffer. * This buffer is guaranteed to have a final \0 character. * This buffer must be released by the caller. */ int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, char **sorted_buf, size_t * sorted_buf_len) { size_t start, finish, regex_len, type_len, context_len; size_t line_len, buf_remainder, i; ssize_t sanity_check; const char *line_buf, *line_end; char *sorted_buf_pos; int escape_chars, just_saw_escape; semanage_file_context_node_t *temp; semanage_file_context_node_t *head; semanage_file_context_node_t *current; semanage_file_context_bucket_t *master; semanage_file_context_bucket_t *bcurrent; i = 0; if (sh == NULL) { return -1; } if (buf == NULL) { ERR(sh, "Received NULL buffer."); return -1; } if (buf_len <= 0) { ERR(sh, "Received buffer of length 0."); return -1; } /* Initialize the head of the linked list * that will contain a node for each file context line. */ head = current = (semanage_file_context_node_t *) calloc(1, sizeof (semanage_file_context_node_t)); if (!head) { ERR(sh, "Failure allocating memory."); return -1; } /* Parse the char buffer into a semanage_file_context_node_t linked list. */ line_buf = buf; buf_remainder = buf_len; while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) { line_len = line_end - line_buf + 1; sanity_check = buf_remainder - line_len; buf_remainder = buf_remainder - line_len; if (sanity_check < 0) { ERR(sh, "Failure parsing file context buffer."); semanage_fc_node_list_destroy(head); return -1; } if (line_len == 0 || line_len == 1) { line_buf = line_end + 1; continue; } /* Skip the whitespace at the front of the line. */ for (i = 0; i < line_len; i++) { if (!isspace(line_buf[i])) break; } /* Check for a blank line. */ if (i >= line_len) { line_buf = line_end + 1; continue; } /* Check if the line is a comment. */ if (line_buf[i] == '#') { line_buf = line_end + 1; continue; } /* Allocate a new node. */ temp = (semanage_file_context_node_t *) calloc(1, sizeof (semanage_file_context_node_t)); if (!temp) { ERR(sh, "Failure allocating memory."); semanage_fc_node_list_destroy(head); return -1; } temp->next = NULL; /* Extract the regular expression from the line. */ escape_chars = 0; just_saw_escape = 0; start = i; while (i < line_len && (!isspace(line_buf[i]))) { if (line_buf[i] == '\\') { if (!just_saw_escape) { escape_chars++; just_saw_escape = 1; } else { /* We're looking at an escaped escape. Reset our flag. */ just_saw_escape = 0; } } else { just_saw_escape = 0; } i++; } finish = i; regex_len = finish - start; if (regex_len == 0) { ERR(sh, "WARNING: semanage_fc_sort: Regex of length 0."); semanage_fc_node_destroy(temp); line_buf = line_end + 1; continue; } temp->path = (char *)strndup(&line_buf[start], regex_len); if (!temp->path) { ERR(sh, "Failure allocating memory."); semanage_fc_node_destroy(temp); semanage_fc_node_list_destroy(head); return -1; } /* Skip the whitespace after the regular expression. */ for (; i < line_len; i++) { if (!isspace(line_buf[i])) break; } if (i == line_len) { ERR(sh, "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path); semanage_fc_node_destroy(temp); line_buf = line_end + 1; continue; } /* Extract the inode type from the line (if it exists). */ if (line_buf[i] == '-') { type_len = 2; /* defined as '--', '-d', '-f', etc. */ if (i + type_len >= line_len) { ERR(sh, "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path); semanage_fc_node_destroy(temp); line_buf = line_end + 1; continue; } /* Record the inode type. */ temp->file_type = (char *)strndup(&line_buf[i], type_len); if (!temp->file_type) { ERR(sh, "Failure allocating memory."); semanage_fc_node_destroy(temp); semanage_fc_node_list_destroy(head); return -1; } i += type_len; /* Skip the whitespace after the type. */ for (; i < line_len; i++) { if (!isspace(line_buf[i])) break; } if (i == line_len) { ERR(sh, "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path); semanage_fc_node_destroy(temp); line_buf = line_end + 1; continue; } } else { type_len = 0; /* inode type did not exist in the file context */ } /* Extract the context from the line. */ start = i; while (i < line_len && (!isspace(line_buf[i]))) i++; finish = i; context_len = finish - start; temp->context = (char *)strndup(&line_buf[start], context_len); if (!temp->context) { ERR(sh, "Failure allocating memory."); semanage_fc_node_destroy(temp); semanage_fc_node_list_destroy(head); return -1; } /* Initialize the data about the file context. */ temp->path_len = regex_len; temp->effective_len = regex_len - escape_chars; temp->type_len = type_len; temp->context_len = context_len; semanage_fc_find_meta(temp); /* Add this node to the end of the linked list. */ current->next = temp; current = current->next; line_buf = line_end + 1; } /* Create the bucket linked list from the node linked list. */ current = head->next; bcurrent = master = (semanage_file_context_bucket_t *) calloc(1, sizeof(semanage_file_context_bucket_t)); if (!master) { ERR(sh, "Failure allocating memory."); semanage_fc_node_list_destroy(head); return -1; } /* Free the head node, as it is no longer used. */ semanage_fc_node_destroy(head); head = NULL; /* Place each node into a bucket. */ while (current) { bcurrent->data = current; current = current->next; /* Detach the node in the bucket from the old list. */ bcurrent->data->next = NULL; /* If we need another bucket, add one to the end. */ if (current) { bcurrent->next = (semanage_file_context_bucket_t *) calloc(1, sizeof(semanage_file_context_bucket_t)); if (!(bcurrent->next)) { ERR(sh, "Failure allocating memory."); semanage_fc_bucket_list_destroy(master); return -1; } bcurrent = bcurrent->next; } } /* Sort the bucket list. */ semanage_fc_merge_sort(master); /* First, calculate how much space we'll need for * the newly sorted block of data. (We don't just * use buf_len for this because we have extracted * comments and whitespace.) */ i = 0; current = master->data; while (current) { i += current->path_len + 1; /* +1 for a tab */ if (current->file_type) { i += current->type_len + 1; /* +1 for a tab */ } i += current->context_len + 1; /* +1 for a newline */ current = current->next; } i = i + 1; /* +1 for trailing \0 */ /* Allocate the buffer for the sorted list. */ *sorted_buf = calloc(i, sizeof(char)); if (!*sorted_buf) { ERR(sh, "Failure allocating memory."); semanage_fc_bucket_list_destroy(master); return -1; } *sorted_buf_len = i; /* Output the sorted semanage_file_context linked list to the char buffer. */ sorted_buf_pos = *sorted_buf; current = master->data; while (current) { /* Output the path. */ i = current->path_len + 1; /* +1 for tab */ snprintf(sorted_buf_pos, i + 1, "%s\t", current->path); sorted_buf_pos = sorted_buf_pos + i; /* Output the type, if there is one. */ if (current->file_type) { i = strlen(current->file_type) + 1; /* +1 for tab */ snprintf(sorted_buf_pos, i + 1, "%s\t", current->file_type); sorted_buf_pos = sorted_buf_pos + i; } /* Output the context. */ i = strlen(current->context) + 1; /* +1 for newline */ snprintf(sorted_buf_pos, i + 1, "%s\n", current->context); sorted_buf_pos = sorted_buf_pos + i; current = current->next; } /* Clean up. */ semanage_fc_bucket_list_destroy(master); /* Sanity check. */ sorted_buf_pos++; if ((sorted_buf_pos - *sorted_buf) != (ssize_t) * sorted_buf_len) { ERR(sh, "Failure writing sorted buffer."); free(*sorted_buf); *sorted_buf = NULL; return -1; } return 0; } /********************* functions that sort netfilter contexts *********************/ #define NC_SORT_NAMES { "pre", "base", "module", "local", "post" } #define NC_SORT_NAMES_LEN { 3, 4, 6, 5, 4 } #define NC_SORT_NEL 5 static void semanage_nc_destroy_ruletab(semanage_netfilter_context_node_t * ruletab[NC_SORT_NEL][2]) { semanage_netfilter_context_node_t *curr, *next; int i; for (i = 0; i < NC_SORT_NEL; i++) { for (curr = ruletab[i][0]; curr != NULL; curr = next) { next = curr->next; free(curr->rule); free(curr); } } } /* Entry function for sorting a set of netfilter context lines. * Returns 0 on success, -1 on failure. * Allocates a buffer pointed to by sorted_buf that contains the sorted lines. * sorted_buf_len is set to the size of this buffer. * This buffer is guaranteed to have a final \0 character. * This buffer must be released by the caller. */ int semanage_nc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, char **sorted_buf, size_t * sorted_buf_len) { /* parsing bits */ const char *priority_names[] = NC_SORT_NAMES; const int priority_names_len[] = NC_SORT_NAMES_LEN; size_t line_len, buf_remainder, i, offset; const char *line_buf, *line_end; /* ruletab bits */ /* keep track of the head (index 0) and tail (index 1) with this array */ semanage_netfilter_context_node_t *ruletab[NC_SORT_NEL][2]; semanage_netfilter_context_node_t *curr, *node; int priority; /* sorted buffer bits */ char *sorted_buf_pos; size_t count; /* initialize ruletab */ memset(ruletab, 0, NC_SORT_NEL * 2 * sizeof(semanage_netfilter_context_node_t *)); /* while lines to be read */ line_buf = buf; buf_remainder = buf_len; while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) { line_len = line_end - line_buf + 1; buf_remainder = buf_remainder - line_len; if (line_len == 0 || line_len == 1) { line_buf = line_end + 1; continue; } /* Skip the whitespace at the front of the line. */ for (i = 0; i < line_len; i++) { if (!isspace(line_buf[i])) break; } /* Check for a blank line. */ if (i >= line_len) { line_buf = line_end + 1; continue; } /* Check if the line is a comment. */ if (line_buf[i] == '#') { line_buf = line_end + 1; continue; } /* extract priority */ priority = -1; offset = 0; for (i = 0; i < NC_SORT_NEL; i++) { if (strncmp (line_buf, priority_names[i], priority_names_len[i]) == 0) { priority = i; offset = priority_names_len[i]; break; } } if (priority < 0) { ERR(sh, "Netfilter context line missing priority."); semanage_nc_destroy_ruletab(ruletab); return -1; } /* skip over whitespace */ for (; offset < line_len && isspace(line_buf[offset]); offset++) ; /* load rule into node */ node = (semanage_netfilter_context_node_t *) malloc(sizeof(semanage_netfilter_context_node_t)); if (!node) { ERR(sh, "Failure allocating memory."); semanage_nc_destroy_ruletab(ruletab); return -1; } node->rule = (char *)strndup(line_buf + offset, line_len - offset); node->rule_len = line_len - offset; node->next = NULL; if (!node->rule) { ERR(sh, "Failure allocating memory."); free(node); semanage_nc_destroy_ruletab(ruletab); return -1; } /* add node to rule table */ if (ruletab[priority][0] && ruletab[priority][1]) { /* add to end of list, update tail pointer */ ruletab[priority][1]->next = node; ruletab[priority][1] = node; } else { /* this list is empty, make head and tail point to the node */ ruletab[priority][0] = ruletab[priority][1] = node; } line_buf = line_end + 1; } /* First, calculate how much space we'll need for * the newly sorted block of data. (We don't just * use buf_len for this because we have extracted * comments and whitespace.) Start at 1 for trailing \0 */ count = 1; for (i = 0; i < NC_SORT_NEL; i++) for (curr = ruletab[i][0]; curr != NULL; curr = curr->next) count += curr->rule_len; /* Allocate the buffer for the sorted list. */ *sorted_buf = calloc(count, sizeof(char)); if (!*sorted_buf) { ERR(sh, "Failure allocating memory."); semanage_nc_destroy_ruletab(ruletab); return -1; } *sorted_buf_len = count; /* write out rule buffer */ sorted_buf_pos = *sorted_buf; for (i = 0; i < NC_SORT_NEL; i++) { for (curr = ruletab[i][0]; curr != NULL; curr = curr->next) { /* put rule into buffer */ snprintf(sorted_buf_pos, curr->rule_len + 1, "%s\n", curr->rule); /* +1 for newline */ sorted_buf_pos = sorted_buf_pos + curr->rule_len; } } /* free ruletab */ semanage_nc_destroy_ruletab(ruletab); return 0; } libsemanage/src/semanage_store.h0100644 0000000 0000000 00000011551 13756670064 016031 0ustar000000000 0000000 /* Authors: Karl MacMillan * Joshua Brindle * Jason Tang * Christopher Ashworth * * Copyright (C) 2004-2006 Tresys Technology, LLC * Copyright (C) 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEMANAGE_MODULE_STORE_H #define SEMANAGE_MODULE_STORE_H #include #include #include #include "handle.h" enum semanage_store_defs { SEMANAGE_ACTIVE, SEMANAGE_PREVIOUS, SEMANAGE_TMP, SEMANAGE_NUM_STORES }; /* sandbox filenames and paths */ enum semanage_sandbox_defs { SEMANAGE_TOPLEVEL, SEMANAGE_MODULES, SEMANAGE_LINKED, SEMANAGE_HOMEDIR_TMPL, SEMANAGE_FC_TMPL, SEMANAGE_COMMIT_NUM_FILE, SEMANAGE_IBPKEYS_LOCAL, SEMANAGE_IBENDPORTS_LOCAL, SEMANAGE_PORTS_LOCAL, SEMANAGE_INTERFACES_LOCAL, SEMANAGE_NODES_LOCAL, SEMANAGE_BOOLEANS_LOCAL, SEMANAGE_SEUSERS_LOCAL, SEMANAGE_SEUSERS_LINKED, SEMANAGE_USERS_BASE_LOCAL, SEMANAGE_USERS_EXTRA_LOCAL, SEMANAGE_USERS_EXTRA_LINKED, SEMANAGE_USERS_EXTRA, SEMANAGE_DISABLE_DONTAUDIT, SEMANAGE_PRESERVE_TUNABLES, SEMANAGE_MODULES_DISABLED, SEMANAGE_STORE_KERNEL, SEMANAGE_STORE_FC_LOCAL, SEMANAGE_STORE_FC_HOMEDIRS, SEMANAGE_STORE_FC, SEMANAGE_STORE_SEUSERS, SEMANAGE_STORE_NUM_PATHS }; enum semanage_final_defs { SEMANAGE_FINAL_TMP, SEMANAGE_FINAL_SELINUX, SEMANAGE_FINAL_NUM }; enum semanage_final_path_defs { SEMANAGE_FINAL_TOPLEVEL, SEMANAGE_FC, SEMANAGE_FC_BIN, SEMANAGE_FC_HOMEDIRS, SEMANAGE_FC_HOMEDIRS_BIN, SEMANAGE_FC_LOCAL, SEMANAGE_FC_LOCAL_BIN, SEMANAGE_KERNEL, SEMANAGE_NC, SEMANAGE_SEUSERS, SEMANAGE_FINAL_PATH_NUM }; /* FIXME: this needs to be made a module store specific init and the * global configuration moved to another file. */ char *semanage_conf_path(void); int semanage_check_init(semanage_handle_t *sh, const char *prefix); extern const char *semanage_fname(enum semanage_sandbox_defs file_enum); extern const char *semanage_path(enum semanage_store_defs store, enum semanage_sandbox_defs file); extern const char *semanage_final_path(enum semanage_final_defs root, enum semanage_final_path_defs suffix); int semanage_create_store(semanage_handle_t * sh, int create); int semanage_store_access_check(void); int semanage_remove_directory(const char *path); int semanage_mkdir(semanage_handle_t *sh, const char *path); int semanage_mkpath(semanage_handle_t *sh, const char *path); int semanage_make_sandbox(semanage_handle_t * sh); int semanage_make_final(semanage_handle_t * sh); int semanage_get_cil_paths(semanage_handle_t * sh, semanage_module_info_t *modinfos, int len, char ***filenames); int semanage_get_active_modules(semanage_handle_t *sh, semanage_module_info_t **modinfo, int *num_modules); /* lock file routines */ int semanage_get_trans_lock(semanage_handle_t * sh); int semanage_get_active_lock(semanage_handle_t * sh); void semanage_release_trans_lock(semanage_handle_t * sh); void semanage_release_active_lock(semanage_handle_t * sh); int semanage_direct_get_serial(semanage_handle_t * sh); int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int num_modules); int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * policydb, enum semanage_sandbox_defs file); int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * policydb, enum semanage_sandbox_defs file); int semanage_install_sandbox(semanage_handle_t * sh); int semanage_verify_modules(semanage_handle_t * sh, char **module_filenames, int num_modules); int semanage_verify_linked(semanage_handle_t * sh); int semanage_verify_kernel(semanage_handle_t * sh); int semanage_split_fc(semanage_handle_t * sh); /* sort file context routines */ int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, char **sorted_buf, size_t * sorted_buf_len); /* sort netfilter context routines */ int semanage_nc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, char **sorted_buf, size_t * sorted_buf_len); int semanage_copy_file(const char *src, const char *dst, mode_t mode); #endif libsemanage/src/semanageswig.i0100644 0000000 0000000 00000004660 13756670064 015513 0ustar000000000 0000000 /* Author: Spencer Shimko * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2006 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ %module semanage /* pull in the headers */ %include "../include/semanage/debug.h" %include "../include/semanage/handle.h" %include "../include/semanage/modules.h" %include "../include/semanage/context_record.h" %include "../include/semanage/boolean_record.h" %include "../include/semanage/booleans_policy.h" %include "../include/semanage/booleans_local.h" %include "../include/semanage/booleans_active.h" %include "../include/semanage/iface_record.h" %include "../include/semanage/interfaces_local.h" %include "../include/semanage/interfaces_policy.h" %include "../include/semanage/user_record.h" %include "../include/semanage/users_local.h" %include "../include/semanage/users_policy.h" %include "../include/semanage/port_record.h" %include "../include/semanage/ports_local.h" %include "../include/semanage/ports_policy.h" %include "../include/semanage/ibpkey_record.h" %include "../include/semanage/ibpkeys_local.h" %include "../include/semanage/ibpkeys_policy.h" %include "../include/semanage/ibendport_record.h" %include "../include/semanage/ibendports_local.h" %include "../include/semanage/ibendports_policy.h" %include "../include/semanage/fcontext_record.h" %include "../include/semanage/fcontexts_local.h" %include "../include/semanage/fcontexts_policy.h" %include "../include/semanage/seuser_record.h" %include "../include/semanage/seusers_local.h" %include "../include/semanage/seusers_policy.h" %include "../include/semanage/node_record.h" %include "../include/semanage/nodes_local.h" %include "../include/semanage/nodes_policy.h" %include "../include/semanage/semanage.h" libsemanage/src/semanageswig_python.i0100644 0000000 0000000 00000037022 13756670064 017112 0ustar000000000 0000000 /* Author: Spencer Shimko * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2006 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** standard typemaps **/ %header %{ #include #include #include #define STATUS_SUCCESS 0 #define STATUS_ERR -1 %} %include "stdint.i" %ignore semanage_module_install_pp; %ignore semanage_module_install_hll; %wrapper %{ /* There are two ways to call this function: * One is with a valid swig_type and destructor. * Two is with a NULL swig_type and NULL destructor. * * In the first mode, the function converts * an array of *cloned* objects [of the given pointer swig type] * into a PyList, and destroys the array in the process * (the objects pointers are preserved). * * In the second mode, the function converts * an array of *constant* strings into a PyList, and destroys * the array in the process * (the strings are copied, originals not freed). */ static int semanage_array2plist( semanage_handle_t* handle, void** arr, unsigned int asize, swig_type_info* swig_type, void (*destructor) (void*), PyObject** result) { PyObject* plist = PyList_New(0); unsigned int i; if (!plist) goto err; for (i = 0; i < asize; i++) { PyObject* obj = NULL; /* NULL indicates string conversion, * otherwise create an opaque pointer */ if (!swig_type) obj = SWIG_FromCharPtr(arr[i]); else obj = SWIG_NewPointerObj(arr[i], swig_type, 0); if (!obj) goto err; if (PyList_Append(plist, obj) < 0) goto err; } free(arr); *result = plist; return STATUS_SUCCESS; err: for (i = 0; i < asize; i++) if (destructor) destructor(arr[i]); free(arr); return STATUS_ERR; } %} /* a few helpful typemaps are available in this library */ %include /* wrap all int*'s so they can be used for results if it becomes necessary to send in data this should be changed to INOUT */ %apply int *OUTPUT { int * }; %apply int *OUTPUT { size_t * }; %apply int *OUTPUT { unsigned int * }; %apply int *OUTPUT { uint16_t * }; %include /* This is needed to properly mmaped binary data in SWIG */ %cstring_output_allocate_size(void **mapped_data, size_t *data_len, munmap(*$1, *$2)); %typemap(in, numinputs=0) char **(char *temp=NULL) { $1 = &temp; } %typemap(argout) char** { $result = SWIG_Python_AppendOutput($result, SWIG_FromCharPtr(*$1)); free(*$1); } %typemap(in, numinputs=0) char ***(char **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, const semanage_user_t* user, const char*** roles_arr, unsigned int* num_roles) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$3, *$4, NULL, NULL, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } /** module typemaps**/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_module_info_t ** parameter */ %typemap(in, numinputs=0) semanage_module_info_t **(semanage_module_info_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_module_info_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } /** module key typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_module_key_t ** parameter */ %typemap(in, numinputs=0) semanage_module_key_t **(semanage_module_key_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_module_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } /** context typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_context_t ** parameter */ %typemap(in, numinputs=0) semanage_context_t **(semanage_context_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_context_t** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } /** boolean typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_bool_t *** parameter */ %typemap(in, numinputs=0) semanage_bool_t ***(semanage_bool_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_bool_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_bool, (void (*) (void*)) &semanage_bool_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_bool_t **(semanage_bool_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_bool_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_bool_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_bool_key_t **(semanage_bool_key_t *temp=NULL) { $1 = &temp; } /** fcontext typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_fcontext_t *** parameter */ %typemap(in, numinputs=0) semanage_fcontext_t ***(semanage_fcontext_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_fcontext_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_fcontext, (void (*) (void*)) &semanage_fcontext_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_fcontext_t **(semanage_fcontext_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_fcontext_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_fcontext_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_fcontext_key_t **(semanage_fcontext_key_t *temp=NULL) { $1 = &temp; } /** interface typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_iface_t *** parameter */ %typemap(in, numinputs=0) semanage_iface_t ***(semanage_iface_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_iface_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_iface, (void (*) (void*)) &semanage_iface_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_iface_t **(semanage_iface_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_iface_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_iface_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_iface_key_t **(semanage_iface_key_t *temp=NULL) { $1 = &temp; } /** seuser typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_seuser_t *** parameter */ %typemap(in, numinputs=0) semanage_seuser_t ***(semanage_seuser_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_seuser_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_seuser, (void (*) (void*)) &semanage_seuser_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_seuser_t **(semanage_seuser_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_seuser_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_seuser_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_seuser_key_t **(semanage_seuser_key_t *temp=NULL) { $1 = &temp; } /** user typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_user_t *** parameter */ %typemap(in, numinputs=0) semanage_user_t ***(semanage_user_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_user_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_user, (void (*) (void*)) &semanage_user_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_user_t **(semanage_user_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_user_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_user_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_user_key_t **(semanage_user_key_t *temp=NULL) { $1 = &temp; } /** port typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_port_t *** parameter */ %typemap(in, numinputs=0) semanage_port_t ***(semanage_port_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_port_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_port, (void (*) (void*)) &semanage_port_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_port_t **(semanage_port_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_port_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_port_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_port_key_t **(semanage_port_key_t *temp=NULL) { $1 = &temp; } /** ibpkey typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_ibpkey_t *** parameter */ %typemap(in, numinputs=0) semanage_ibpkey_t ***(semanage_ibpkey_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_ibpkey_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_ibpkey, (void (*) (void*)) &semanage_ibpkey_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_ibpkey_t **(semanage_ibpkey_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_ibpkey_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_ibpkey_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_ibpkey_key_t **(semanage_ibpkey_key_t *temp=NULL) { $1 = &temp; } /** ibendport typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_ibendport_t *** parameter */ %typemap(in, numinputs=0) semanage_ibendport_t ***(semanage_ibendport_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_ibendport_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_ibendport, (void (*) (void*)) &semanage_ibendport_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_ibendport_t **(semanage_ibendport_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_ibendport_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_ibendport_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_ibendport_key_t **(semanage_ibendport_key_t *temp=NULL) { $1 = &temp; } /** node typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_node_t *** parameter */ %typemap(in, numinputs=0) semanage_node_t ***(semanage_node_t **temp=NULL) { $1 = &temp; } %typemap(argout) ( semanage_handle_t* handle, semanage_node_t*** records, unsigned int* count) { if ($result) { int value; SWIG_AsVal_int($result, &value); if (value >= 0) { PyObject* plist = NULL; if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_node, (void (*) (void*)) &semanage_node_free, &plist) < 0) $result = SWIG_From_int(STATUS_ERR); else $result = SWIG_Python_AppendOutput($result, plist); } } } %typemap(in, numinputs=0) semanage_node_t **(semanage_node_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_node_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_node_key_t ** { $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_node_key_t **(semanage_node_key_t *temp=NULL) { $1 = &temp; } %include "semanageswig_python_exception.i" %include "semanageswig.i" libsemanage/src/semanageswig_ruby.i0100644 0000000 0000000 00000015400 13756670064 016546 0ustar000000000 0000000 /* Author Dave Quigley * based on semanageswig_python.i by Spencer Shimko */ %header %{ #include #include #define STATUS_SUCCESS 0 #define STATUS_ERR -1 %} /* a few helpful typemaps are available in this library */ %include /* wrap all int*'s so they can be used for results if it becomes necessary to send in data this should be changed to INOUT */ %apply int *OUTPUT { int * }; %apply int *OUTPUT { size_t * }; %apply int *OUTPUT { unsigned int * }; %typemap(in, numinputs=0) char **(char *temp=NULL) { $1 = &temp; } %typemap(argout) char** { %append_output(SWIG_FromCharPtr(*$1)); free(*$1); } %typemap(in, numinputs=0) char ***(char **temp=NULL) { $1 = &temp; } /* the wrapper will setup this parameter for passing... the resulting ruby functions will not take the semanage_module_info_t ** parameter */ %typemap(in, numinputs=0) semanage_module_info_t **(semanage_module_info_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_module_info_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } /** context typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_context_t ** parameter */ %typemap(in, numinputs=0) semanage_context_t **(semanage_context_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_context_t** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } /** boolean typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_bool_t *** parameter */ %typemap(in, numinputs=0) semanage_bool_t ***(semanage_bool_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_bool_t **(semanage_bool_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_bool_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_bool_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_bool_key_t **(semanage_bool_key_t *temp=NULL) { $1 = &temp; } /** fcontext typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_fcontext_t *** parameter */ %typemap(in, numinputs=0) semanage_fcontext_t ***(semanage_fcontext_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_fcontext_t **(semanage_fcontext_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_fcontext_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_fcontext_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_fcontext_key_t **(semanage_fcontext_key_t *temp=NULL) { $1 = &temp; } /** interface typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_iface_t *** parameter */ %typemap(in, numinputs=0) semanage_iface_t ***(semanage_iface_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_iface_t **(semanage_iface_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_iface_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_iface_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_iface_key_t **(semanage_iface_key_t *temp=NULL) { $1 = &temp; } /** seuser typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_seuser_t *** parameter */ %typemap(in, numinputs=0) semanage_seuser_t ***(semanage_seuser_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_seuser_t **(semanage_seuser_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_seuser_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_seuser_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_seuser_key_t **(semanage_seuser_key_t *temp=NULL) { $1 = &temp; } /** user typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_user_t *** parameter */ %typemap(in, numinputs=0) semanage_user_t ***(semanage_user_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_user_t **(semanage_user_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_user_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_user_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_user_key_t **(semanage_user_key_t *temp=NULL) { $1 = &temp; } /** port typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_port_t *** parameter */ %typemap(in, numinputs=0) semanage_port_t ***(semanage_port_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_port_t **(semanage_port_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_port_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_port_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_port_key_t **(semanage_port_key_t *temp=NULL) { $1 = &temp; } /** node typemaps **/ /* the wrapper will setup this parameter for passing... the resulting python functions will not take the semanage_node_t *** parameter */ %typemap(in, numinputs=0) semanage_node_t ***(semanage_node_t **temp=NULL) { $1 = &temp; } %typemap(in, numinputs=0) semanage_node_t **(semanage_node_t *temp=NULL) { $1 = &temp; } %typemap(argout) semanage_node_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(argout) semanage_node_key_t ** { $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(in, numinputs=0) semanage_node_key_t **(semanage_node_key_t *temp=NULL) { $1 = &temp; } %include "semanageswig.i" libsemanage/src/seuser_internal.h0100644 0000000 0000000 00000002570 13756670064 016240 0ustar000000000 0000000 #ifndef _SEMANAGE_SEUSER_INTERNAL_H_ #define _SEMANAGE_SEUSER_INTERNAL_H_ #include #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_seuser_clone) hidden_proto(semanage_seuser_compare) hidden_proto(semanage_seuser_compare2) hidden_proto(semanage_seuser_create) hidden_proto(semanage_seuser_free) hidden_proto(semanage_seuser_get_mlsrange) hidden_proto(semanage_seuser_get_name) hidden_proto(semanage_seuser_get_sename) hidden_proto(semanage_seuser_key_create) hidden_proto(semanage_seuser_key_extract) hidden_proto(semanage_seuser_key_free) hidden_proto(semanage_seuser_set_mlsrange) hidden_proto(semanage_seuser_set_name) hidden_proto(semanage_seuser_set_sename) hidden_proto(semanage_seuser_iterate) hidden_proto(semanage_seuser_iterate_local) /* SEUSER RECORD: method table */ extern record_table_t SEMANAGE_SEUSER_RTABLE; extern int seuser_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void seuser_file_dbase_release(dbase_config_t * dconfig); extern int hidden semanage_seuser_validate_local(semanage_handle_t * handle, const sepol_policydb_t * policydb); #endif libsemanage/src/seuser_record.c0100644 0000000 0000000 00000013460 13756670064 015675 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_seuser_t (Unix User) * Object: semanage_seuser_key_t (Unix User Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ struct semanage_seuser; struct semanage_seuser_key; typedef struct semanage_seuser record_t; typedef struct semanage_seuser_key record_key_t; #define DBASE_RECORD_DEFINED #include #include #include "seuser_internal.h" #include "debug.h" #include #include "database.h" struct semanage_seuser { /* This user's name */ char *name; /* This user's corresponding * seuser ("role set") */ char *sename; /* This user's mls range (only required for mls) */ char *mls_range; }; struct semanage_seuser_key { /* This user's name */ char *name; }; int semanage_seuser_key_create(semanage_handle_t * handle, const char *name, semanage_seuser_key_t ** key_ptr) { semanage_seuser_key_t *tmp_key = (semanage_seuser_key_t *) malloc(sizeof(semanage_seuser_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create seuser key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, could not create seuser key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(semanage_seuser_key_create) int semanage_seuser_key_extract(semanage_handle_t * handle, const semanage_seuser_t * seuser, semanage_seuser_key_t ** key_ptr) { if (semanage_seuser_key_create(handle, seuser->name, key_ptr) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not extract seuser key from record"); return STATUS_ERR; } hidden_def(semanage_seuser_key_extract) void semanage_seuser_key_free(semanage_seuser_key_t * key) { free(key->name); free(key); } hidden_def(semanage_seuser_key_free) int semanage_seuser_compare(const semanage_seuser_t * seuser, const semanage_seuser_key_t * key) { return strcmp(seuser->name, key->name); } hidden_def(semanage_seuser_compare) int semanage_seuser_compare2(const semanage_seuser_t * seuser, const semanage_seuser_t * seuser2) { return strcmp(seuser->name, seuser2->name); } hidden_def(semanage_seuser_compare2) static int semanage_seuser_compare2_qsort(const semanage_seuser_t ** seuser, const semanage_seuser_t ** seuser2) { return strcmp((*seuser)->name, (*seuser2)->name); } /* Name */ const char *semanage_seuser_get_name(const semanage_seuser_t * seuser) { return seuser->name; } hidden_def(semanage_seuser_get_name) int semanage_seuser_set_name(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set seuser (Unix) name"); return STATUS_ERR; } free(seuser->name); seuser->name = tmp_name; return STATUS_SUCCESS; } hidden_def(semanage_seuser_set_name) /* Selinux Name */ const char *semanage_seuser_get_sename(const semanage_seuser_t * seuser) { return seuser->sename; } hidden_def(semanage_seuser_get_sename) int semanage_seuser_set_sename(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *sename) { char *tmp_sename = strdup(sename); if (!tmp_sename) { ERR(handle, "out of memory, could not set seuser (SELinux) name"); return STATUS_ERR; } free(seuser->sename); seuser->sename = tmp_sename; return STATUS_SUCCESS; } hidden_def(semanage_seuser_set_sename) /* MLS Range */ const char *semanage_seuser_get_mlsrange(const semanage_seuser_t * seuser) { return seuser->mls_range; } hidden_def(semanage_seuser_get_mlsrange) int semanage_seuser_set_mlsrange(semanage_handle_t * handle, semanage_seuser_t * seuser, const char *mls_range) { char *tmp_mls_range = strdup(mls_range); if (!tmp_mls_range) { ERR(handle, "out of memory, could not set seuser MLS range"); return STATUS_ERR; } free(seuser->mls_range); seuser->mls_range = tmp_mls_range; return STATUS_SUCCESS; } hidden_def(semanage_seuser_set_mlsrange) /* Create */ int semanage_seuser_create(semanage_handle_t * handle, semanage_seuser_t ** seuser_ptr) { semanage_seuser_t *seuser = (semanage_seuser_t *) malloc(sizeof(semanage_seuser_t)); if (!seuser) { ERR(handle, "out of memory, could not create seuser"); return STATUS_ERR; } seuser->name = NULL; seuser->sename = NULL; seuser->mls_range = NULL; *seuser_ptr = seuser; return STATUS_SUCCESS; } hidden_def(semanage_seuser_create) /* Deep copy clone */ int semanage_seuser_clone(semanage_handle_t * handle, const semanage_seuser_t * seuser, semanage_seuser_t ** seuser_ptr) { semanage_seuser_t *new_seuser = NULL; if (semanage_seuser_create(handle, &new_seuser) < 0) goto err; if (semanage_seuser_set_name(handle, new_seuser, seuser->name) < 0) goto err; if (semanage_seuser_set_sename(handle, new_seuser, seuser->sename) < 0) goto err; if (seuser->mls_range && (semanage_seuser_set_mlsrange(handle, new_seuser, seuser->mls_range) < 0)) goto err; *seuser_ptr = new_seuser; return STATUS_SUCCESS; err: ERR(handle, "could not clone seuser"); semanage_seuser_free(new_seuser); return STATUS_ERR; } hidden_def(semanage_seuser_clone) /* Destroy */ void semanage_seuser_free(semanage_seuser_t * seuser) { if (!seuser) return; free(seuser->name); free(seuser->sename); free(seuser->mls_range); free(seuser); } hidden_def(semanage_seuser_free) /* Record base functions */ record_table_t SEMANAGE_SEUSER_RTABLE = { .create = semanage_seuser_create, .key_extract = semanage_seuser_key_extract, .key_free = semanage_seuser_key_free, .clone = semanage_seuser_clone, .compare = semanage_seuser_compare, .compare2 = semanage_seuser_compare2, .compare2_qsort = semanage_seuser_compare2_qsort, .free = semanage_seuser_free, }; libsemanage/src/seusers_file.c0100644 0000000 0000000 00000005706 13756670064 015525 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_seuser; struct semanage_seuser_key; typedef struct semanage_seuser record_t; typedef struct semanage_seuser_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include "seuser_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" #include "handle.h" static int seuser_print(semanage_handle_t * handle, semanage_seuser_t * seuser, FILE * str) { const char *name = semanage_seuser_get_name(seuser); const char *sename = semanage_seuser_get_sename(seuser); const char *mls = semanage_seuser_get_mlsrange(seuser); if (fprintf(str, "%s:%s", name, sename) < 0) goto err; if (mls != NULL && fprintf(str, ":%s", mls) < 0) goto err; fprintf(str, "\n"); return STATUS_SUCCESS; err: ERR(handle, "could not print seuser %s to stream", name); return STATUS_ERR; } static int seuser_parse(semanage_handle_t * handle, parse_info_t * info, semanage_seuser_t * seuser) { char *str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Extract name */ if (parse_fetch_string(handle, info, &str, ':') < 0) goto err; if (semanage_seuser_set_name(handle, seuser, str) < 0) goto err; free(str); str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_ch(handle, info, ':') < 0) goto err; if (parse_skip_space(handle, info) < 0) goto err; /* Extract sename */ if (parse_fetch_string(handle, info, &str, ':') < 0) goto err; if (semanage_seuser_set_sename(handle, seuser, str) < 0) goto err; free(str); str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_ch(info, ':') == STATUS_NODATA) goto out; if (parse_skip_space(handle, info) < 0) goto err; /* NOTE: does not allow spaces/multiline */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_seuser_set_mlsrange(handle, seuser, str) < 0) goto err; free(str); str = NULL; if (parse_assert_space(handle, info) < 0) goto err; out: return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse seuser record"); free(str); parse_dispose_line(info); return STATUS_ERR; } /* SEUSER RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_SEUSER_FILE_RTABLE = { .parse = seuser_parse, .print = seuser_print, }; int seuser_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_SEUSER_RTABLE, &SEMANAGE_SEUSER_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void seuser_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/seusers_local.c0100644 0000000 0000000 00000021364 13756670064 015676 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_seuser; struct semanage_seuser_key; typedef struct semanage_seuser_key record_key_t; typedef struct semanage_seuser record_t; #define DBASE_RECORD_DEFINED #include #include #include #include #include "user_internal.h" #include "seuser_internal.h" #include "handle.h" #include "database.h" #include "debug.h" #include "string.h" #include static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) { char *roles = NULL; unsigned int num_roles; size_t i; size_t size = 0; const char **roles_arr; semanage_user_key_t *key = NULL; semanage_user_t * user; if (semanage_user_key_create(handle, sename, &key) >= 0) { if (semanage_user_query(handle, key, &user) >= 0) { if (semanage_user_get_roles(handle, user, &roles_arr, &num_roles) >= 0) { for (i = 0; imsg_callback; dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); const char *sename = semanage_seuser_get_sename(data); const char *mls_range = semanage_seuser_get_mlsrange(data); semanage_seuser_t *previous = NULL; semanage_seuser_t *new = NULL; if (!sename) { errno=EINVAL; return -1; } rc = semanage_seuser_clone(handle, data, &new); if (rc < 0) { goto err; } if (!mls_range && semanage_mls_enabled(handle)) { semanage_user_key_t *ukey = NULL; semanage_user_t *u = NULL; rc = semanage_user_key_create(handle, sename, &ukey); if (rc < 0) goto err; rc = semanage_user_query(handle, ukey, &u); semanage_user_key_free(ukey); if (rc >= 0 ) { mls_range = semanage_user_get_mlsrange(u); rc = semanage_seuser_set_mlsrange(handle, new, mls_range); semanage_user_free(u); } if (rc < 0) goto err; } handle->msg_callback = NULL; (void) semanage_seuser_query(handle, key, &previous); handle->msg_callback = callback; rc = dbase_modify(handle, dconfig, key, new); if (semanage_seuser_audit(handle, new, previous, AUDIT_ROLE_ASSIGN, rc == 0) < 0) rc = -1; err: if (previous) semanage_seuser_free(previous); semanage_seuser_free(new); return rc; } int semanage_seuser_del_local(semanage_handle_t * handle, const semanage_seuser_key_t * key) { int rc; semanage_seuser_t *seuser = NULL; dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); rc = dbase_del(handle, dconfig, key); semanage_seuser_query(handle, key, &seuser); if (semanage_seuser_audit(handle, NULL, seuser, AUDIT_ROLE_REMOVE, rc == 0) < 0) rc = -1; if (seuser) semanage_seuser_free(seuser); return rc; } int semanage_seuser_query_local(semanage_handle_t * handle, const semanage_seuser_key_t * key, semanage_seuser_t ** response) { dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); return dbase_query(handle, dconfig, key, response); } int semanage_seuser_exists_local(semanage_handle_t * handle, const semanage_seuser_key_t * key, int *response) { dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_seuser_count_local(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); return dbase_count(handle, dconfig, response); } int semanage_seuser_iterate_local(semanage_handle_t * handle, int (*handler) (const semanage_seuser_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } hidden_def(semanage_seuser_iterate_local) int semanage_seuser_list_local(semanage_handle_t * handle, semanage_seuser_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); return dbase_list(handle, dconfig, records, count); } struct validate_handler_arg { semanage_handle_t *handle; const sepol_policydb_t *policydb; }; static int validate_handler(const semanage_seuser_t * seuser, void *varg) { semanage_user_t *user = NULL; semanage_user_key_t *key = NULL; int exists, mls_ok; /* Unpack varg */ struct validate_handler_arg *arg = (struct validate_handler_arg *)varg; semanage_handle_t *handle = arg->handle; const sepol_policydb_t *policydb = arg->policydb; /* Unpack seuser */ const char *name = semanage_seuser_get_name(seuser); const char *sename = semanage_seuser_get_sename(seuser); const char *mls_range = semanage_seuser_get_mlsrange(seuser); const char *user_mls_range; /* Make sure the (SElinux) user exists */ if (semanage_user_key_create(handle, sename, &key) < 0) goto err; if (semanage_user_exists(handle, key, &exists) < 0) goto err; if (!exists) { ERR(handle, "selinux user %s does not exist", sename); goto invalid; } /* Verify that the mls range is valid, and that it's contained * within the (SELinux) user mls range. This range is optional */ if (mls_range && sepol_policydb_mls_enabled(policydb)) { if (semanage_user_query(handle, key, &user) < 0) goto err; user_mls_range = semanage_user_get_mlsrange(user); if (sepol_mls_check(handle->sepolh, policydb, mls_range) < 0) goto invalid; if (sepol_mls_contains(handle->sepolh, policydb, user_mls_range, mls_range, &mls_ok) < 0) goto err; if (!mls_ok) { ERR(handle, "MLS range %s for Unix user %s " "exceeds allowed range %s for SELinux user %s", mls_range, name, user_mls_range, sename); goto invalid; } } else if (mls_range) { ERR(handle, "MLS is disabled, but MLS range %s " "was found for Unix user %s", mls_range, name); goto invalid; } semanage_user_key_free(key); semanage_user_free(user); return 0; err: ERR(handle, "could not check if seuser mapping for %s is valid", name); semanage_user_key_free(key); semanage_user_free(user); return -1; invalid: if (mls_range) ERR(handle, "seuser mapping [%s -> (%s, %s)] is invalid", name, sename, mls_range); else ERR(handle, "seuser mapping [%s -> %s] is invalid", name, sename); semanage_user_key_free(key); semanage_user_free(user); return -1; } /* This function may not be called outside a transaction, or * it will (1) deadlock, because iterate is not reentrant outside * a transaction, and (2) be racy, because it makes multiple dbase calls */ int hidden semanage_seuser_validate_local(semanage_handle_t * handle, const sepol_policydb_t * policydb) { struct validate_handler_arg arg; arg.handle = handle; arg.policydb = policydb; return semanage_seuser_iterate_local(handle, validate_handler, &arg); } libsemanage/src/seusers_policy.c0100644 0000000 0000000 00000003134 13756670064 016076 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_seuser; struct semanage_seuser_key; typedef struct semanage_seuser_key record_key_t; typedef struct semanage_seuser record_t; #define DBASE_RECORD_DEFINED #include #include #include "user_internal.h" #include "seuser_internal.h" #include "handle.h" #include "database.h" #include "debug.h" int semanage_seuser_query(semanage_handle_t * handle, const semanage_seuser_key_t * key, semanage_seuser_t ** response) { dbase_config_t *dconfig = semanage_seuser_dbase_policy(handle); return dbase_query(handle, dconfig, key, response); } int semanage_seuser_exists(semanage_handle_t * handle, const semanage_seuser_key_t * key, int *response) { dbase_config_t *dconfig = semanage_seuser_dbase_policy(handle); return dbase_exists(handle, dconfig, key, response); } int semanage_seuser_count(semanage_handle_t * handle, unsigned int *response) { dbase_config_t *dconfig = semanage_seuser_dbase_policy(handle); return dbase_count(handle, dconfig, response); } int semanage_seuser_iterate(semanage_handle_t * handle, int (*handler) (const semanage_seuser_t * record, void *varg), void *handler_arg) { dbase_config_t *dconfig = semanage_seuser_dbase_policy(handle); return dbase_iterate(handle, dconfig, handler, handler_arg); } hidden_def(semanage_seuser_iterate) int semanage_seuser_list(semanage_handle_t * handle, semanage_seuser_t *** records, unsigned int *count) { dbase_config_t *dconfig = semanage_seuser_dbase_policy(handle); return dbase_list(handle, dconfig, records, count); } libsemanage/src/user_base_record.c0100644 0000000 0000000 00000010620 13756670064 016332 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_user_base_t (SELinux User/Class Policy Object) * Object: semanage_user_key_t (SELinux User/Class Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include typedef sepol_user_key_t semanage_user_key_t; #define _SEMANAGE_USER_KEY_DEFINED_ typedef sepol_user_t semanage_user_base_t; #define _SEMANAGE_USER_BASE_DEFINED_ typedef semanage_user_base_t record_t; typedef semanage_user_key_t record_key_t; #define DBASE_RECORD_DEFINED #include #include "user_internal.h" #include "handle.h" #include "database.h" #include "debug.h" /* Key */ hidden int semanage_user_base_key_extract(semanage_handle_t * handle, const semanage_user_base_t * user, semanage_user_key_t ** key) { return sepol_user_key_extract(handle->sepolh, user, key); } static int semanage_user_base_compare(const semanage_user_base_t * user, const semanage_user_key_t * key) { return sepol_user_compare(user, key); } static int semanage_user_base_compare2(const semanage_user_base_t * user, const semanage_user_base_t * user2) { return sepol_user_compare2(user, user2); } static int semanage_user_base_compare2_qsort(const semanage_user_base_t ** user, const semanage_user_base_t ** user2) { return sepol_user_compare2(*user, *user2); } /* Name */ hidden const char *semanage_user_base_get_name(const semanage_user_base_t * user) { return sepol_user_get_name(user); } hidden int semanage_user_base_set_name(semanage_handle_t * handle, semanage_user_base_t * user, const char *name) { return sepol_user_set_name(handle->sepolh, user, name); } /* MLS */ hidden const char *semanage_user_base_get_mlslevel(const semanage_user_base_t * user) { return sepol_user_get_mlslevel(user); } hidden int semanage_user_base_set_mlslevel(semanage_handle_t * handle, semanage_user_base_t * user, const char *mls_level) { return sepol_user_set_mlslevel(handle->sepolh, user, mls_level); } hidden const char *semanage_user_base_get_mlsrange(const semanage_user_base_t * user) { return sepol_user_get_mlsrange(user); } hidden int semanage_user_base_set_mlsrange(semanage_handle_t * handle, semanage_user_base_t * user, const char *mls_range) { return sepol_user_set_mlsrange(handle->sepolh, user, mls_range); } /* Role management */ hidden int semanage_user_base_get_num_roles(const semanage_user_base_t * user) { return sepol_user_get_num_roles(user); } hidden int semanage_user_base_add_role(semanage_handle_t * handle, semanage_user_base_t * user, const char *role) { return sepol_user_add_role(handle->sepolh, user, role); } hidden void semanage_user_base_del_role(semanage_user_base_t * user, const char *role) { sepol_user_del_role(user, role); } hidden int semanage_user_base_has_role(const semanage_user_base_t * user, const char *role) { return sepol_user_has_role(user, role); } hidden int semanage_user_base_get_roles(semanage_handle_t * handle, const semanage_user_base_t * user, const char ***roles_arr, unsigned int *num_roles) { return sepol_user_get_roles(handle->sepolh, user, roles_arr, num_roles); } hidden int semanage_user_base_set_roles(semanage_handle_t * handle, semanage_user_base_t * user, const char **roles_arr, unsigned int num_roles) { return sepol_user_set_roles(handle->sepolh, user, roles_arr, num_roles); } /* Create/Clone/Destroy */ hidden int semanage_user_base_create(semanage_handle_t * handle, semanage_user_base_t ** user_ptr) { return sepol_user_create(handle->sepolh, user_ptr); } hidden int semanage_user_base_clone(semanage_handle_t * handle, const semanage_user_base_t * user, semanage_user_base_t ** user_ptr) { return sepol_user_clone(handle->sepolh, user, user_ptr); } hidden void semanage_user_base_free(semanage_user_base_t * user) { sepol_user_free(user); } /* Record base functions */ record_table_t SEMANAGE_USER_BASE_RTABLE = { .create = semanage_user_base_create, .key_extract = semanage_user_base_key_extract, .key_free = semanage_user_key_free, .clone = semanage_user_base_clone, .compare = semanage_user_base_compare, .compare2 = semanage_user_base_compare2, .compare2_qsort = semanage_user_base_compare2_qsort, .free = semanage_user_base_free, }; libsemanage/src/user_extra_record.c0100644 0000000 0000000 00000011152 13756670064 016544 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_user_extra_t (SELinux User/Class Extra Data) * Object: semanage_user_extra_key_t (SELinux User/Class Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include typedef sepol_user_key_t semanage_user_key_t; #define _SEMANAGE_USER_KEY_DEFINED_ struct semanage_user_extra; typedef struct semanage_user_extra record_t; typedef semanage_user_key_t record_key_t; #define DBASE_RECORD_DEFINED #include #include #include #include "user_internal.h" #include "debug.h" #include "database.h" struct semanage_user_extra { /* This user's name */ char *name; /* Labeling prefix */ char *prefix; }; static int semanage_user_extra_key_extract(semanage_handle_t * handle, const semanage_user_extra_t * user_extra, semanage_user_key_t ** key_ptr) { if (semanage_user_key_create(handle, user_extra->name, key_ptr) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not extract key from user extra record"); return STATUS_ERR; } static int semanage_user_extra_compare(const semanage_user_extra_t * user_extra, const semanage_user_key_t * key) { const char *name; semanage_user_key_unpack(key, &name); return strcmp(user_extra->name, name); } static int semanage_user_extra_compare2(const semanage_user_extra_t * user_extra, const semanage_user_extra_t * user_extra2) { return strcmp(user_extra->name, user_extra2->name); } static int semanage_user_extra_compare2_qsort(const semanage_user_extra_t ** user_extra, const semanage_user_extra_t ** user_extra2) { return strcmp((*user_extra)->name, (*user_extra2)->name); } /* Name */ hidden const char *semanage_user_extra_get_name(const semanage_user_extra_t * user_extra) { return user_extra->name; } hidden int semanage_user_extra_set_name(semanage_handle_t * handle, semanage_user_extra_t * user_extra, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set name %s " "for user extra data", name); return STATUS_ERR; } free(user_extra->name); user_extra->name = tmp_name; return STATUS_SUCCESS; } /* Labeling prefix */ hidden const char *semanage_user_extra_get_prefix(const semanage_user_extra_t * user_extra) { return user_extra->prefix; } hidden int semanage_user_extra_set_prefix(semanage_handle_t * handle, semanage_user_extra_t * user_extra, const char *prefix) { char *tmp_prefix = strdup(prefix); if (!tmp_prefix) { ERR(handle, "out of memory, could not set prefix %s " "for user %s", prefix, user_extra->name); return STATUS_ERR; } free(user_extra->prefix); user_extra->prefix = tmp_prefix; return STATUS_SUCCESS; } /* Create */ hidden int semanage_user_extra_create(semanage_handle_t * handle, semanage_user_extra_t ** user_extra_ptr) { semanage_user_extra_t *user_extra = (semanage_user_extra_t *) malloc(sizeof(semanage_user_extra_t)); if (!user_extra) { ERR(handle, "out of memory, could not " "create user extra data record"); return STATUS_ERR; } user_extra->name = NULL; user_extra->prefix = NULL; *user_extra_ptr = user_extra; return STATUS_SUCCESS; } /* Destroy */ hidden void semanage_user_extra_free(semanage_user_extra_t * user_extra) { if (!user_extra) return; free(user_extra->name); free(user_extra->prefix); free(user_extra); } /* Deep copy clone */ hidden int semanage_user_extra_clone(semanage_handle_t * handle, const semanage_user_extra_t * user_extra, semanage_user_extra_t ** user_extra_ptr) { semanage_user_extra_t *new_user_extra = NULL; if (semanage_user_extra_create(handle, &new_user_extra) < 0) goto err; if (semanage_user_extra_set_name (handle, new_user_extra, user_extra->name) < 0) goto err; if (semanage_user_extra_set_prefix (handle, new_user_extra, user_extra->prefix) < 0) goto err; *user_extra_ptr = new_user_extra; return STATUS_SUCCESS; err: ERR(handle, "could not clone extra data for user %s", user_extra->name); semanage_user_extra_free(new_user_extra); return STATUS_ERR; } /* Record base functions */ record_table_t SEMANAGE_USER_EXTRA_RTABLE = { .create = semanage_user_extra_create, .key_extract = semanage_user_extra_key_extract, .key_free = semanage_user_key_free, .clone = semanage_user_extra_clone, .compare = semanage_user_extra_compare, .compare2 = semanage_user_extra_compare2, .compare2_qsort = semanage_user_extra_compare2_qsort, .free = semanage_user_extra_free, }; libsemanage/src/user_internal.h0100644 0000000 0000000 00000013560 13756670064 015711 0ustar000000000 0000000 #ifndef _SEMANAGE_USER_INTERNAL_H_ #define _SEMANAGE_USER_INTERNAL_H_ #include #include #include #include #include "database.h" #include "handle.h" #include "dso.h" hidden_proto(semanage_user_add_role) hidden_proto(semanage_user_clone) hidden_proto(semanage_user_compare) hidden_proto(semanage_user_compare2) hidden_proto(semanage_user_create) hidden_proto(semanage_user_free) hidden_proto(semanage_user_get_mlslevel) hidden_proto(semanage_user_get_mlsrange) hidden_proto(semanage_user_get_name) hidden_proto(semanage_user_get_roles) hidden_proto(semanage_user_key_create) hidden_proto(semanage_user_key_extract) hidden_proto(semanage_user_key_free) hidden_proto(semanage_user_set_mlslevel) hidden_proto(semanage_user_set_mlsrange) hidden_proto(semanage_user_set_name) hidden_proto(semanage_user_exists) hidden_proto(semanage_user_query) /* USER record: metod table */ extern record_table_t SEMANAGE_USER_RTABLE; /* USER BASE record: method table */ extern record_table_t SEMANAGE_USER_BASE_RTABLE; /* USER EXTRA record: method table */ extern record_table_t SEMANAGE_USER_EXTRA_RTABLE; /* ============ Init/Release functions ========== */ /* USER BASE record, FILE backend */ extern int user_base_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void user_base_file_dbase_release(dbase_config_t * dconfig); /* USER EXTRA record, FILE backend */ extern int user_extra_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig); extern void user_extra_file_dbase_release(dbase_config_t * dconfig); /* USER BASE record, POLICYDB backend */ extern int user_base_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig); extern void user_base_policydb_dbase_release(dbase_config_t * dconfig); /* USER record, JOIN backend */ extern int user_join_dbase_init(semanage_handle_t * handle, dbase_config_t * join1, dbase_config_t * join2, dbase_config_t * dconfig); extern void user_join_dbase_release(dbase_config_t * dconfig); /*======= Internal API: Base (Policy) User record ====== */ #ifndef _SEMANAGE_USER_BASE_DEFINED_ struct semanage_user_base; typedef struct semanage_user_base semanage_user_base_t; #define _SEMANAGE_USER_BASE_DEFINED_ #endif hidden int semanage_user_base_create(semanage_handle_t * handle, semanage_user_base_t ** user_ptr); hidden int semanage_user_base_clone(semanage_handle_t * handle, const semanage_user_base_t * user, semanage_user_base_t ** user_ptr); hidden int semanage_user_base_key_extract(semanage_handle_t * handle, const semanage_user_base_t * user, semanage_user_key_t ** key); hidden const char *semanage_user_base_get_name(const semanage_user_base_t * user); hidden int semanage_user_base_set_name(semanage_handle_t * handle, semanage_user_base_t * user, const char *name); hidden const char *semanage_user_base_get_mlslevel(const semanage_user_base_t * user); hidden int semanage_user_base_set_mlslevel(semanage_handle_t * handle, semanage_user_base_t * user, const char *mls_level); hidden const char *semanage_user_base_get_mlsrange(const semanage_user_base_t * user); hidden int semanage_user_base_set_mlsrange(semanage_handle_t * handle, semanage_user_base_t * user, const char *mls_range); hidden int semanage_user_base_get_num_roles(const semanage_user_base_t * user); hidden int semanage_user_base_add_role(semanage_handle_t * handle, semanage_user_base_t * user, const char *role); hidden void semanage_user_base_del_role(semanage_user_base_t * user, const char *role); hidden int semanage_user_base_has_role(const semanage_user_base_t * user, const char *role); hidden int semanage_user_base_get_roles(semanage_handle_t * handle, const semanage_user_base_t * user, const char ***roles_arr, unsigned int *num_roles); hidden int semanage_user_base_set_roles(semanage_handle_t * handle, semanage_user_base_t * user, const char **roles_arr, unsigned int num_roles); hidden void semanage_user_base_free(semanage_user_base_t * user); /*=========== Internal API: Extra User record ==========*/ struct semanage_user_extra; typedef struct semanage_user_extra semanage_user_extra_t; hidden int semanage_user_extra_create(semanage_handle_t * handle, semanage_user_extra_t ** user_extra_ptr); hidden int semanage_user_extra_clone(semanage_handle_t * handle, const semanage_user_extra_t * user_extra, semanage_user_extra_t ** user_extra_ptr); hidden const char *semanage_user_extra_get_name(const semanage_user_extra_t * user_extra); hidden int semanage_user_extra_set_name(semanage_handle_t * handle, semanage_user_extra_t * user_extra, const char *name); hidden const char *semanage_user_extra_get_prefix(const semanage_user_extra_t * user_extra); hidden int semanage_user_extra_set_prefix(semanage_handle_t * handle, semanage_user_extra_t * user_extra, const char *prefix); hidden void semanage_user_extra_free(semanage_user_extra_t * user_extra); /*======== Internal API: Join record ========== */ hidden void semanage_user_key_unpack(const semanage_user_key_t * key, const char **name); hidden int semanage_user_join(semanage_handle_t * handle, const semanage_user_base_t * record1, const semanage_user_extra_t * record2, semanage_user_t ** result); hidden int semanage_user_split(semanage_handle_t * handle, const semanage_user_t * record, semanage_user_base_t ** split1, semanage_user_extra_t ** split2); #endif libsemanage/src/user_record.c0100644 0000000 0000000 00000022430 13756670064 015342 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ /* Object: semanage_user_t (SELinux User/Class) * Object: semanage_user_key_t (SELinux User/Class Key) * Implements: record_t (Database Record) * Implements: record_key_t (Database Record Key) */ #include typedef sepol_user_key_t semanage_user_key_t; #define _SEMANAGE_USER_KEY_DEFINED_ struct semanage_user; typedef struct semanage_user record_t; typedef semanage_user_key_t record_key_t; #define DBASE_RECORD_DEFINED #include #include #include "user_internal.h" #include "handle.h" #include "database.h" #include "debug.h" struct semanage_user { char *name; semanage_user_base_t *base; semanage_user_extra_t *extra; }; /* Key */ int semanage_user_key_create(semanage_handle_t * handle, const char *name, semanage_user_key_t ** key) { return sepol_user_key_create(handle->sepolh, name, key); } hidden_def(semanage_user_key_create) int semanage_user_key_extract(semanage_handle_t * handle, const semanage_user_t * user, semanage_user_key_t ** key) { return semanage_user_base_key_extract(handle, user->base, key); } hidden_def(semanage_user_key_extract) void semanage_user_key_free(semanage_user_key_t * key) { sepol_user_key_free(key); } hidden_def(semanage_user_key_free) hidden void semanage_user_key_unpack(const semanage_user_key_t * key, const char **name) { sepol_user_key_unpack(key, name); } int semanage_user_compare(const semanage_user_t * user, const semanage_user_key_t * key) { const char *name; sepol_user_key_unpack(key, &name); return strcmp(user->name, name); } hidden_def(semanage_user_compare) int semanage_user_compare2(const semanage_user_t * user, const semanage_user_t * user2) { return strcmp(user->name, user2->name); } hidden_def(semanage_user_compare2) static int semanage_user_compare2_qsort(const semanage_user_t ** user, const semanage_user_t ** user2) { return strcmp((*user)->name, (*user2)->name); } /* Name */ const char *semanage_user_get_name(const semanage_user_t * user) { return user->name; } hidden_def(semanage_user_get_name) int semanage_user_set_name(semanage_handle_t * handle, semanage_user_t * user, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) goto omem; if (semanage_user_base_set_name(handle, user->base, name) < 0) goto err; if (semanage_user_extra_set_name(handle, user->extra, name) < 0) goto err; free(user->name); user->name = tmp_name; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not set user name to %s", name); free(tmp_name); return STATUS_ERR; } hidden_def(semanage_user_set_name) /* Labeling prefix */ const char *semanage_user_get_prefix(const semanage_user_t * user) { return semanage_user_extra_get_prefix(user->extra); } int semanage_user_set_prefix(semanage_handle_t * handle, semanage_user_t * user, const char *name) { return semanage_user_extra_set_prefix(handle, user->extra, name); } /* MLS */ const char *semanage_user_get_mlslevel(const semanage_user_t * user) { return semanage_user_base_get_mlslevel(user->base); } hidden_def(semanage_user_get_mlslevel) int semanage_user_set_mlslevel(semanage_handle_t * handle, semanage_user_t * user, const char *mls_level) { return semanage_user_base_set_mlslevel(handle, user->base, mls_level); } hidden_def(semanage_user_set_mlslevel) const char *semanage_user_get_mlsrange(const semanage_user_t * user) { return semanage_user_base_get_mlsrange(user->base); } hidden_def(semanage_user_get_mlsrange) int semanage_user_set_mlsrange(semanage_handle_t * handle, semanage_user_t * user, const char *mls_range) { return semanage_user_base_set_mlsrange(handle, user->base, mls_range); } hidden_def(semanage_user_set_mlsrange) /* Role management */ int semanage_user_get_num_roles(const semanage_user_t * user) { return semanage_user_base_get_num_roles(user->base); } int semanage_user_add_role(semanage_handle_t * handle, semanage_user_t * user, const char *role) { return semanage_user_base_add_role(handle, user->base, role); } hidden_def(semanage_user_add_role) void semanage_user_del_role(semanage_user_t * user, const char *role) { semanage_user_base_del_role(user->base, role); } int semanage_user_has_role(const semanage_user_t * user, const char *role) { return semanage_user_base_has_role(user->base, role); } int semanage_user_get_roles(semanage_handle_t * handle, const semanage_user_t * user, const char ***roles_arr, unsigned int *num_roles) { return semanage_user_base_get_roles(handle, user->base, roles_arr, num_roles); } hidden_def(semanage_user_get_roles) int semanage_user_set_roles(semanage_handle_t * handle, semanage_user_t * user, const char **roles_arr, unsigned int num_roles) { return semanage_user_base_set_roles(handle, user->base, roles_arr, num_roles); } /* Create/Clone/Destroy */ int semanage_user_create(semanage_handle_t * handle, semanage_user_t ** user_ptr) { semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t)); if (!tmp_user) goto omem; if (semanage_user_base_create(handle, &tmp_user->base) < 0) goto err; if (semanage_user_extra_create(handle, &tmp_user->extra) < 0) goto err; /* Initialize the prefix for migration purposes */ if (semanage_user_extra_set_prefix(handle, tmp_user->extra, "user") < 0) goto err; *user_ptr = tmp_user; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not create user record"); semanage_user_free(tmp_user); return STATUS_ERR; } hidden_def(semanage_user_create) int semanage_user_clone(semanage_handle_t * handle, const semanage_user_t * user, semanage_user_t ** user_ptr) { semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t)); if (!tmp_user) goto omem; /* Clone base and extra records */ if (semanage_user_base_clone(handle, user->base, &tmp_user->base) < 0) goto err; if (semanage_user_extra_clone(handle, user->extra, &tmp_user->extra) < 0) goto err; /* Set the shared name */ if (semanage_user_set_name(handle, tmp_user, user->name) < 0) goto err; *user_ptr = tmp_user; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone user record"); semanage_user_free(tmp_user); return STATUS_ERR; } hidden_def(semanage_user_clone) void semanage_user_free(semanage_user_t * user) { if (!user) return; semanage_user_base_free(user->base); semanage_user_extra_free(user->extra); free(user->name); free(user); } hidden_def(semanage_user_free) /* Join properties */ hidden int semanage_user_join(semanage_handle_t * handle, const semanage_user_base_t * record1, const semanage_user_extra_t * record2, semanage_user_t ** result) { const char *name; semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t)); if (!tmp_user) goto omem; /* Set the shared name from one of the records * (at least one is available) */ if (record1 == NULL) name = semanage_user_extra_get_name(record2); else name = semanage_user_base_get_name(record1); /* Join base record if it exists, create a blank one otherwise */ if (record1) { if (semanage_user_base_clone(handle, record1, &tmp_user->base) < 0) goto err; } else { if (semanage_user_base_create(handle, &tmp_user->base) < 0) goto err; if (semanage_user_base_set_name(handle, tmp_user->base, name) < 0) goto err; } /* Join extra record if it exists, create a blank one otherwise */ if (record2) { if (semanage_user_extra_clone(handle, record2, &tmp_user->extra) < 0) goto err; } else { if (semanage_user_extra_create(handle, &tmp_user->extra) < 0) goto err; if (semanage_user_extra_set_name(handle, tmp_user->extra, name) < 0) goto err; if (semanage_user_extra_set_prefix (handle, tmp_user->extra, "user") < 0) goto err; } if (semanage_user_set_name(handle, tmp_user, name) < 0) goto err; *result = tmp_user; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not join data records for user %s", semanage_user_base_get_name(record1)); semanage_user_free(tmp_user); return STATUS_ERR; } hidden int semanage_user_split(semanage_handle_t * handle, const semanage_user_t * record, semanage_user_base_t ** split1, semanage_user_extra_t ** split2) { semanage_user_base_t *tmp_base_user = NULL; semanage_user_extra_t *tmp_extra_user = NULL; if (semanage_user_base_clone(handle, record->base, &tmp_base_user) < 0) goto err; if (semanage_user_extra_clone(handle, record->extra, &tmp_extra_user) < 0) goto err; *split1 = tmp_base_user; *split2 = tmp_extra_user; return STATUS_SUCCESS; err: ERR(handle, "could not split data records for user %s", semanage_user_get_name(record)); semanage_user_base_free(tmp_base_user); semanage_user_extra_free(tmp_extra_user); return STATUS_ERR; } /* Record base functions */ record_table_t SEMANAGE_USER_RTABLE = { .create = semanage_user_create, .key_extract = semanage_user_key_extract, .key_free = semanage_user_key_free, .clone = semanage_user_clone, .compare = semanage_user_compare, .compare2 = semanage_user_compare2, .compare2_qsort = semanage_user_compare2_qsort, .free = semanage_user_free, }; libsemanage/src/users_base_file.c0100644 0000000 0000000 00000011650 13756670064 016162 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user_base; struct semanage_user_key; typedef struct semanage_user_base record_t; typedef struct semanage_user_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include #include #include "user_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int user_base_print(semanage_handle_t * handle, semanage_user_base_t * user, FILE * str) { const char **roles = NULL; unsigned int i, nroles; const char *name = semanage_user_base_get_name(user); const char *mls_level = semanage_user_base_get_mlslevel(user); const char *mls_range = semanage_user_base_get_mlsrange(user); if (fprintf(str, "user %s roles { ", name) < 0) goto err; if (semanage_user_base_get_roles(handle, user, &roles, &nroles) < 0) goto err; for (i = 0; i < nroles; i++) { if (fprintf(str, "%s ", roles[i]) < 0) goto err; } if (fprintf(str, "} ") < 0) goto err; /* MLS */ if (mls_level != NULL && mls_range != NULL) if (fprintf(str, "level %s range %s", mls_level, mls_range) < 0) goto err; if (fprintf(str, ";\n") < 0) goto err; free(roles); return STATUS_SUCCESS; err: free(roles); ERR(handle, "could not print user %s to stream", name); return STATUS_ERR; } static int user_base_parse(semanage_handle_t * handle, parse_info_t * info, semanage_user_base_t * user) { int islist = 0; char *str = NULL; char *start; char *name_str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Parse user header */ if (parse_assert_str(handle, info, "user") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Parse user name */ if (parse_fetch_string(handle, info, &name_str, ' ') < 0) goto err; if (semanage_user_base_set_name(handle, user, name_str) < 0) { free(name_str); goto err; } free(name_str); if (parse_assert_space(handle, info) < 0) goto err; if (parse_assert_str(handle, info, "roles") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; islist = (parse_optional_ch(info, '{') != STATUS_NODATA); /* For each role, loop */ do { char delim; if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_noeof(handle, info) < 0) goto err; start = info->ptr; while (*(info->ptr) && *(info->ptr) != ';' && *(info->ptr) != '}' && !isspace(*(info->ptr))) info->ptr++; delim = *(info->ptr); *(info->ptr)++ = '\0'; if (semanage_user_base_add_role(handle, user, start) < 0) goto err; if (delim && !isspace(delim)) { if (islist && delim == '}') break; else if (!islist && delim == ';') goto skip_semicolon; else goto err; } if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_ch(info, ';') != STATUS_NODATA) goto skip_semicolon; if (parse_optional_ch(info, '}') != STATUS_NODATA) islist = 0; } while (islist); /* Handle mls */ /* Parse level header */ if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_str(info, "level") == STATUS_NODATA) goto semicolon; if (parse_assert_space(handle, info) < 0) goto err; /* NOTE: does not allow spaces/multiline */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_user_base_set_mlslevel(handle, user, str) < 0) goto err; free(str); str = NULL; /* Parse range header */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_assert_str(handle, info, "range") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* NOTE: does not allow spaces/multiline */ if (parse_fetch_string(handle, info, &str, ';') < 0) goto err; if (semanage_user_base_set_mlsrange(handle, user, str) < 0) goto err; free(str); str = NULL; /* Check for semicolon */ semicolon: if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_ch(handle, info, ';') < 0) goto err; skip_semicolon: return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse user record"); free(str); parse_dispose_line(info); return STATUS_ERR; } /* USER BASE record: FILE extension: method table */ record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = { .parse = user_base_parse, .print = user_base_print, }; int user_base_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_USER_BASE_RTABLE, &SEMANAGE_USER_BASE_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void user_base_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/users_base_policydb.c0100644 0000000 0000000 00000004343 13756670064 017051 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user_base; struct semanage_user_key; typedef struct semanage_user_base record_t; typedef struct semanage_user_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_policydb; typedef struct dbase_policydb dbase_t; #define DBASE_DEFINED #include #include #include "user_internal.h" #include "debug.h" #include "database_policydb.h" #include "semanage_store.h" /* USER BASE record: POLICYDB extension: method table */ record_policydb_table_t SEMANAGE_USER_BASE_POLICYDB_RTABLE = { .add = NULL, .modify = (record_policydb_table_modify_t) sepol_user_modify, .set = NULL, .query = (record_policydb_table_query_t) sepol_user_query, .count = (record_policydb_table_count_t) sepol_user_count, .exists = (record_policydb_table_exists_t) sepol_user_exists, .iterate = (record_policydb_table_iterate_t) sepol_user_iterate, }; int user_base_policydb_dbase_init(semanage_handle_t * handle, dbase_config_t * dconfig) { if (dbase_policydb_init(handle, semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL), semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL), &SEMANAGE_USER_BASE_RTABLE, &SEMANAGE_USER_BASE_POLICYDB_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE; return STATUS_SUCCESS; } void user_base_policydb_dbase_release(dbase_config_t * dconfig) { dbase_policydb_release(dconfig->dbase); } libsemanage/src/users_extra_file.c0100644 0000000 0000000 00000005527 13756670064 016401 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user_extra; struct semanage_user_key; typedef struct semanage_user_extra record_t; typedef struct semanage_user_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include #include #include #include "user_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" #include "handle.h" static int user_extra_print(semanage_handle_t * handle, semanage_user_extra_t * user_extra, FILE * str) { const char *name = semanage_user_extra_get_name(user_extra); const char *prefix = semanage_user_extra_get_prefix(user_extra); if (fprintf(str, "user %s prefix %s;\n", name, prefix) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not print user extra data " "for %s to stream", name); return STATUS_ERR; } static int user_extra_parse(semanage_handle_t * handle, parse_info_t * info, semanage_user_extra_t * user_extra) { char *str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* User string */ if (parse_assert_str(handle, info, "user") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Extract name */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_user_extra_set_name(handle, user_extra, str) < 0) goto err; free(str); str = NULL; /* Prefix string */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_assert_str(handle, info, "prefix") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Extract prefix */ if (parse_fetch_string(handle, info, &str, ';') < 0) goto err; if (semanage_user_extra_set_prefix(handle, user_extra, str) < 0) goto err; free(str); str = NULL; /* Semicolon */ if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_ch(handle, info, ';') < 0) goto err; return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse user extra data"); free(str); parse_dispose_line(info); return STATUS_ERR; } /* USER EXTRA RECORD: FILE extension: method table */ record_file_table_t SEMANAGE_USER_EXTRA_FILE_RTABLE = { .parse = user_extra_parse, .print = user_extra_print, }; int user_extra_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_USER_EXTRA_RTABLE, &SEMANAGE_USER_EXTRA_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void user_extra_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); } libsemanage/src/users_join.c0100644 0000000 0000000 00000002246 13756670064 015211 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user; struct semanage_user_key; typedef struct semanage_user record_t; typedef struct semanage_user_key record_key_t; #define DBASE_RECORD_DEFINED struct semanage_user_base; struct semanage_user_extra; typedef struct semanage_user_base record1_t; typedef struct semanage_user_extra record2_t; #define DBASE_RECORD_JOIN_DEFINED struct dbase_join; typedef struct dbase_join dbase_t; #define DBASE_DEFINED #include #include "user_internal.h" #include "database_join.h" #include "debug.h" /* USER record: JOIN extension: method table */ record_join_table_t SEMANAGE_USER_JOIN_RTABLE = { .join = semanage_user_join, .split = semanage_user_split, }; int user_join_dbase_init(semanage_handle_t * handle, dbase_config_t * join1, dbase_config_t * join2, dbase_config_t * dconfig) { if (dbase_join_init(handle, &SEMANAGE_USER_RTABLE, &SEMANAGE_USER_JOIN_RTABLE, join1, join2, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_JOIN_DTABLE; return STATUS_SUCCESS; } void user_join_dbase_release(dbase_config_t * dconfig) { dbase_join_release(dconfig->dbase); } libsemanage/src/users_local.c0100644 0000000 0000000 00000005532 13756670064 015345 0ustar000000000 0000000 /* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user; struct semanage_user_key; typedef struct semanage_user_key record_key_t; typedef struct semanage_user record_t; #define DBASE_RECORD_DEFINED #include #include #include "user_internal.h" #include "seuser_internal.h" #include "handle.h" #include "database.h" #include "errno.h" #include "debug.h" int semanage_user_modify_local(semanage_handle_t * handle, const semanage_user_key_t * key, const semanage_user_t * data) { dbase_config_t *dconfig = semanage_user_dbase_local(handle); return dbase_modify(handle, dconfig, key, data); } static int lookup_seuser(semanage_handle_t * handle, const semanage_user_key_t *k) { semanage_user_t *user; semanage_seuser_t **records; const char *name; const char *sename; unsigned int count; size_t i; int rc = 0; if (semanage_user_query(handle, k, &user) < 0) return 0; name = semanage_user_get_name(user); semanage_seuser_list_local(handle, &records, &count); for(i=0; i * Paul Rosenfeld * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utilities.h" #include #include #include #include #include #include #include #define TRUE 1 #define FALSE 0 char *semanage_findval(const char *file, const char *var, const char *delim) { FILE *fd; char *buff = NULL; char *retval = NULL; size_t buff_len = 0; assert(file); assert(var); if ((fd = fopen(file, "r")) == NULL) return NULL; while (getline(&buff, &buff_len, fd) > 0) { if (semanage_is_prefix(buff, var)) { retval = semanage_split(buff, delim); if (retval) semanage_rtrim(retval, '\n'); break; } } free(buff); fclose(fd); return retval; } int semanage_is_prefix(const char *str, const char *prefix) { if (!str) { return FALSE; } if (!prefix) { return TRUE; } return strncmp(str, prefix, strlen(prefix)) == 0; } char *semanage_split_on_space(const char *str) { /* as per the man page, these are the isspace() chars */ const char *seps = "\f\n\r\t\v "; size_t off = 0; if (!str) return NULL; /* skip one token and the spaces before and after it */ off = strspn(str, seps); off += strcspn(str + off, seps); off += strspn(str + off, seps); return strdup(str + off); } char *semanage_split(const char *str, const char *delim) { char *retval; if (!str) return NULL; if (!delim || !(*delim)) return semanage_split_on_space(str); retval = strstr(str, delim); if (retval == NULL) return NULL; return strdup(retval + strlen(delim)); } int semanage_list_push(semanage_list_t ** list, const char *data) { semanage_list_t *temp = NULL; if (!data) return EINVAL; if (semanage_list_find(*list, data) != NULL) return 0; if (!(temp = malloc(sizeof(semanage_list_t)))) return ENOMEM; if (!(temp->data = strdup(data))) { free(temp); return ENOMEM; } temp->next = *list; *list = temp; return 0; } char *semanage_list_pop(semanage_list_t ** list) { semanage_list_t *node = NULL; char *data = NULL; if (!list || !(*list)) return NULL; node = (*list); data = node->data; (*list) = node->next; free(node); return data; } void semanage_list_destroy(semanage_list_t ** list) { semanage_list_t *temp; while ((temp = (*list))) { free(temp->data); (*list) = temp->next; free(temp); } } semanage_list_t *semanage_list_find(semanage_list_t * l, const char *data) { if (!data) return NULL; while (l && strcmp(l->data, data)) l = l->next; return l; } int semanage_list_sort(semanage_list_t ** l) { semanage_list_t **array = NULL; semanage_list_t *temp = NULL; size_t count = 0; size_t i = 0; if (!l) return 0; for (temp = *l; temp; temp = temp->next) ++count; array = malloc(sizeof(semanage_list_t *) * count); if (!array) return ENOMEM; /* couldn't allocate memory for sort */ for (temp = *l; temp; temp = temp->next) { array[i++] = temp; } qsort(array, count, sizeof(semanage_list_t *), (int (*)(const void *, const void *))&semanage_cmp_plist_t); for (i = 0; i < (count - 1); ++i) { array[i]->next = array[i + 1]; } array[i]->next = NULL; (*l) = array[0]; free(array); return 0; } int semanage_cmp_plist_t(const semanage_list_t ** x, const semanage_list_t ** y) { return strcmp((*x)->data, (*y)->data); } int semanage_str_count(const char *data, char what) { int count = 0; if (!data) return 0; while (*data) { if (*data == what) ++count; ++data; } return count; } void semanage_rtrim(char *str, char trim_to) { int len = 0; if (!str) return; len = strlen(str); while (len > 0) { if (str[--len] == trim_to) { str[len] = '\0'; return; } } } char *semanage_str_replace(const char *search, const char *replace, const char *src, size_t lim) { size_t count = 0, slen, rlen, newsize; char *p, *pres, *result; const char *psrc; slen = strlen(search); rlen = strlen(replace); /* Do not support empty search strings */ if (slen == 0) return NULL; /* Count the occurences of search in src and compute the new size */ for (p = strstr(src, search); p != NULL; p = strstr(p + slen, search)) { count++; if (lim && count >= lim) break; } if (!count) return strdup(src); /* Allocate the result string */ newsize = strlen(src) + 1 + count * (rlen - slen); result = malloc(newsize); if (!result) return NULL; /* Fill the result */ psrc = src; pres = result; for (p = strstr(src, search); p != NULL; p = strstr(psrc, search)) { /* Copy the part which has not been modified */ if (p != psrc) { size_t length = (size_t)(p - psrc); memcpy(pres, psrc, length); pres += length; } /* Copy the replacement part */ if (rlen != 0) { memcpy(pres, replace, rlen); pres += rlen; } psrc = p + slen; count--; if (!count) break; } /* Copy the last part, after doing a sanity check */ assert(pres + strlen(psrc) + 1 == result + newsize); strcpy(pres, psrc); return result; } /* list_addafter_controlmem does *NOT* duplicate the data argument * use at your own risk, I am building a list out of malloc'd memory and * it is only going to get stored into this list, thus when I destroy it * later I won't free a ptr twice. * * returns the newly created node or NULL on error */ semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data) { semanage_list_t *temp = malloc(sizeof(semanage_list_t)); if (!temp) return NULL; temp->data = data; temp->next = item->next; item->next = temp; return temp; } semanage_list_t *semanage_slurp_file_filter(FILE * file, int (*pred) (const char *)) { semanage_list_t head; semanage_list_t *current = &head; char *line = NULL; size_t buff_len = 0; head.next = NULL; /* initialize head, we aren't going to use the data */ while (getline(&line, &buff_len, file) >= 0) { if (pred(line)) { semanage_rtrim(line, '\n'); current = list_addafter_controlmem(current, line); if (!current) break; line = NULL; buff_len = 0; } } free(line); return head.next; } libsemanage/src/utilities.h0100644 0000000 0000000 00000012365 13756670064 015054 0ustar000000000 0000000 /* Author: Mark Goldman * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file contains helper functions that are loosely based off of what is * available from the python script genhomedircon. Also this file contains * c implementations of a couple of python functions so that genhomedircon will * look/act like the python script. */ #ifndef _SEMANAGE_UTILITIES_H_ #define _SEMANAGE_UTILITIES_H_ #include #if defined(__GNUC__) && !defined(__STRICT_ANSI__) #define WARN_UNUSED \ __attribute__ ((__warn_unused_result__)) #else # define WARN_UNUSED /* nothing */ #endif typedef struct list { char *data; struct list *next; } semanage_list_t; /** * @param file the path to the file to look for a variable in * @param var the variable that you want the value of * @param delim the value that separates the part you care about from the part * that you don't. * @return for the first instance of var in the file, returns everything after * delim. * returns "" if not found IE if(*(semanage_findval(f,v,d)) == '\0'){ * printf("%s not found in file", v); * } * * NULL for error (out of memory, etc) */ char *semanage_findval(const char *file, const char *var, const char *delim) WARN_UNUSED; /** * @param str string to test * @param val prefix * @return 1 if val is the prefix of str * 0 if val is not the prefix of str * * note: if str == NULL, returns false * if val == NULL, returns true --nothing can always be the prefix of * something * if (*val) == "" returns true same as above. */ int semanage_is_prefix(const char *str, const char *val) WARN_UNUSED; /** * @param str the string to semanage_split * @return malloc'd string after the first run of charachters that aren't whitespace */ char *semanage_split_on_space(const char *str) WARN_UNUSED; /** * @param str the string to semanage_split * @param delim the string delimiter. NOT a set of charachters that can be * a delimiter. * if *delim == '\0' behaves as semanage_splitOnSpace() * @return a ptr to the first charachter past the delimiter. * if delim doesn't appear in the string, returns a ptr to the * trailing null in the string */ char *semanage_split(const char *str, const char *delim) WARN_UNUSED; /* linked list string functions * Functions allocate memory. Must be free'd with * either semanage_list_pop until list == NULL or semanage_list_destroy() */ int semanage_list_push(semanage_list_t ** list, const char *data) WARN_UNUSED; char *semanage_list_pop(semanage_list_t ** list); void semanage_list_destroy(semanage_list_t ** list); semanage_list_t *semanage_list_find(semanage_list_t * l, const char *data) WARN_UNUSED; int semanage_list_sort(semanage_list_t ** l) WARN_UNUSED; /* function to compare 2 semanage_list_t nodes, * returns strcmp(x->data, y->data) * used internally by semanage_list_sort() */ int semanage_cmp_plist_t(const semanage_list_t ** x, const semanage_list_t ** y); /** * @param data a target string * @param what a charachter * @returns the number of times the char appears in the string */ int semanage_str_count(const char *data, char what); /** * @param - a string * @param the charachter to trim to * @return - mangles the string, converting the first * occurrance of the charachter to a '\0' from * the end of the string. */ void semanage_rtrim(char *str, char trim_to); /** * @param value being searched for * @param replacement value that replaces found search values * @param string being searched and replaced on * @param maximum number of value occurences (zero for unlimited) * @return newly-allocated string with the replaced values */ char *semanage_str_replace(const char *search, const char *replace, const char *src, size_t lim); /** * @param data some string * @return modifies the string such that the first whitespace char becomes * '\0', ending the string. */ void semanage_keep_until_space(char *data); /** * @param file - an open FILE to read from * @param pred - a function taking a string that * returns 1 if the string should be * kept and 0 otherwise * @return a list of lines from the file (empty lines become * empty strings) in the file order where pred(line) * returns > 0 */ semanage_list_t *semanage_slurp_file_filter(FILE * file, int (*pred) (const char *)) WARN_UNUSED; #endif libsemanage/tests/0040755 0000000 0000000 00000000000 13756670064 013237 5ustar000000000 0000000 libsemanage/tests/.gitignore0100644 0000000 0000000 00000000022 13756670064 015216 0ustar000000000 0000000 libsemanage-tests libsemanage/tests/Makefile0100644 0000000 0000000 00000001125 13756670064 014673 0ustar000000000 0000000 # Add your test source files here: SOURCES = $(sort $(wildcard *.c)) ########################################################################### EXECUTABLE = libsemanage-tests CFLAGS += -g -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter override CFLAGS += -I../src -I../include override LDLIBS += -lcunit -lbz2 -laudit -lselinux -lsepol OBJECTS = $(SOURCES:.c=.o) all: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) ../src/libsemanage.a $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) clean distclean: rm -rf $(OBJECTS) $(EXECUTABLE) test: all ./$(EXECUTABLE) libsemanage/tests/README0100644 0000000 0000000 00000004410 13756670064 014113 0ustar000000000 0000000 Notes on tests ============================ The semanage_access_check test in the semanage_store suite simulates a read-only filesystem by using DAC permissions. Consequently, these tests will fail if run as root, as root can override DAC permissions. How to add and use unit tests ============================= We are using the CUnit unit testing framework. This framework--and the official documentation of the framework--may be found here: http://cunit.sourceforge.net/ If you have not yet installed CUnit, first do that. (There is an RPM, or you can compile from source.) Once installed, follow these steps to add unit tests for your code: 1. Create a .h and .c file corresponding to the .c file you want to test. For example, test_semanage_store.c provides tests of the functions in semanage_store.c. Your new .h/.c files represent a suite of related tests. 2. Write or add new tests to a suite. Tests are simply functions that take the form: void test_my_function(void) These tests are where you will make calls to the CUnit assertions. If you are making a new test suite, also add the suite init/cleanup functions. These take the form: int _test_init(void) int _cleanup(void) These functions will be called before and after the test functions in your suite, respectively. They return 0 on success, 1 on failure. 3. Update libsemanage-tests.c to add your new suite and/or your new tests using the DECLARE_SUITE macro in do_tests(). 4. Update the Makefile: + Make sure that the TESTSRC variable is set to the location of the libsemanage source code you want to test. 5. Compile the libsemanage source code you will be testing, to ensure the object files are available and up to date. 6. Run your tests. Rejoice or despair, as appropriate. A note on the the utilities.c: Add functions that can be commonly used here. For example, it is handy to have a dummy message callback function to silence error messages produced by libsemanage and keep your output pretty. To do this, include utilities.h and specify the callback like so: semanage_handle_t *sh; sh = semanage_handle_create(); sh->msg_callback = test_msg_handler; Feel free to add other such functions here as well. libsemanage/tests/libsemanage-tests.c0100644 0000000 0000000 00000005504 13756670064 017013 0ustar000000000 0000000 /* Authors: Christopher Ashworth * Caleb Case * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test_semanage_store.h" #include "test_utilities.h" #include #include #include #include #include #include #include #define DECLARE_SUITE(name) \ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \ if (NULL == suite) { \ CU_cleanup_registry(); \ return CU_get_error(); } \ if (name##_add_tests(suite)) { \ CU_cleanup_registry(); \ return CU_get_error(); } static void usage(char *progname) { printf("usage: %s [options]\n", progname); printf("options:\n"); printf("\t-v, --verbose\t\t\tverbose output\n"); printf("\t-i, --interactive\t\tinteractive console\n"); } static bool do_tests(int interactive, int verbose) { CU_pSuite suite = NULL; unsigned int num_failures; /* Initialize the CUnit test registry. */ if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); DECLARE_SUITE(semanage_store); DECLARE_SUITE(semanage_utilities); if (verbose) CU_basic_set_mode(CU_BRM_VERBOSE); else CU_basic_set_mode(CU_BRM_NORMAL); if (interactive) CU_console_run_tests(); else CU_basic_run_tests(); num_failures = CU_get_number_of_tests_failed(); CU_cleanup_registry(); return CU_get_error() == CUE_SUCCESS && num_failures == 0; } /* The main function for setting up and running the libsemanage unit tests. * Returns a CUE_SUCCESS on success, or a CUnit error code on failure. */ int main(int argc, char **argv) { int i, verbose = 1, interactive = 0; struct option opts[] = { {"verbose", 0, NULL, 'v'}, {"interactive", 0, NULL, 'i'}, {NULL, 0, NULL, 0} }; while ((i = getopt_long(argc, argv, "vi", opts, NULL)) != -1) { switch (i) { case 'v': verbose = 1; break; case 'i': interactive = 1; break; case 'h': default:{ usage(argv[0]); exit(1); } } } if (!do_tests(interactive, verbose)) return -1; return 0; } libsemanage/tests/nc_sort_malformed0100644 0000000 0000000 00000002216 13756670064 016655 0ustar000000000 0000000 pre *mangle pre :PREROUTING ACCEPT [0:0] pre :INPUT ACCEPT [0:0] pre :FORWARD ACCEPT [0:0] pre :OUTPUT ACCEPT [0:0] pre :POSTROUTING ACCEPT [0:0] pre :selinux_input - [0:0] pre :selinux_output - [0:0] pre :selinux_new_input - [0:0] pre :selinux_new_output - [0:0] pre -A INPUT -j selinux_input pre -A OUTPUT -j selinux_output pre -A selinux_input -m state --state NEW -j selinux_new_input pre -A selinux_input -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore pre -A selinux_output -m state --state NEW -j selinux_new_output pre -A selinux_output -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore pre -A selinux_new_input -j SECMARK --selctx system_u:object_r:server_packet_t base -A selinux_new_input -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_server_packet_t -A selinux_new_input -j CONNSECMARK --save post -A selinux_new_input -j RETURN pre -A selinux_new_output -j SECMARK --selctx system_u:object_r:client_packet_t module -A selinux_new_output -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_client_packet_t post -A selinux_new_output -j CONNSECMARK --save post -A selinux_new_output -j RETURN post COMMIT libsemanage/tests/nc_sort_sorted0100644 0000000 0000000 00000002046 13756670064 016210 0ustar000000000 0000000 *mangle :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] :selinux_input - [0:0] :selinux_output - [0:0] :selinux_new_input - [0:0] :selinux_new_output - [0:0] -A INPUT -j selinux_input -A OUTPUT -j selinux_output -A selinux_input -m state --state NEW -j selinux_new_input -A selinux_input -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore -A selinux_output -m state --state NEW -j selinux_new_output -A selinux_output -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore -A selinux_new_input -j SECMARK --selctx system_u:object_r:server_packet_t -A selinux_new_output -j SECMARK --selctx system_u:object_r:client_packet_t -A selinux_new_input -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_server_packet_t -A selinux_new_output -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_client_packet_t -A selinux_new_input -j CONNSECMARK --save -A selinux_new_input -j RETURN -A selinux_new_output -j CONNSECMARK --save -A selinux_new_output -j RETURN COMMIT libsemanage/tests/nc_sort_unsorted0100644 0000000 0000000 00000002265 13756670064 016556 0ustar000000000 0000000 pre *mangle pre :PREROUTING ACCEPT [0:0] pre :INPUT ACCEPT [0:0] pre :FORWARD ACCEPT [0:0] pre :OUTPUT ACCEPT [0:0] pre :POSTROUTING ACCEPT [0:0] pre :selinux_input - [0:0] pre :selinux_output - [0:0] pre :selinux_new_input - [0:0] pre :selinux_new_output - [0:0] # a comment pre -A INPUT -j selinux_input pre -A OUTPUT -j selinux_output pre -A selinux_input -m state --state NEW -j selinux_new_input pre -A selinux_input -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore pre -A selinux_output -m state --state NEW -j selinux_new_output # another comment pre -A selinux_output -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore base-A selinux_new_input -j SECMARK --selctx system_u:object_r:server_packet_t module -A selinux_new_input -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_server_packet_t post -A selinux_new_input -j CONNSECMARK --save post -A selinux_new_input -j RETURN base -A selinux_new_output -j SECMARK --selctx system_u:object_r:client_packet_t module -A selinux_new_output -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:http_client_packet_t post -A selinux_new_output -j CONNSECMARK --save post -A selinux_new_output -j RETURN post COMMIT libsemanage/tests/test_semanage_store.c0100644 0000000 0000000 00000022043 13756670064 017434 0ustar000000000 0000000 /* Authors: Christopher Ashworth * Caleb Case * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* The purpose of this file is to provide unit tests of the functions in: * * libsemanage/src/semanage_store.c * */ #include "handle.h" #include "semanage_store.h" #include "utilities.h" #include "test_semanage_store.h" #include #include #include #include #include #include #include #include #include #include #include semanage_handle_t *sh = NULL; const char *rootpath = "./test-policy"; const char *polpath = "./test-policy/store/"; const char *readlockpath = "./test-policy/store/semanage.read.LOCK"; const char *translockpath = "./test-policy/store/semanage.trans.LOCK"; const char *actpath = "./test-policy/store/active"; const char *modpath = "./test-policy/store/active/modules"; /* The suite initialization function. * Returns zero on success, non-zero otherwise. */ int semanage_store_test_init(void) { int err; /* create directories */ err = mkdir(rootpath, S_IRUSR | S_IWUSR | S_IXUSR); if (err != 0) return -1; err = mkdir(polpath, S_IRUSR | S_IWUSR | S_IXUSR); if (err != 0) return -1; err = mkdir(actpath, S_IRUSR | S_IWUSR | S_IXUSR); if (err != 0) return -1; err = mkdir(modpath, S_IRUSR | S_IWUSR | S_IXUSR); if (err != 0) return -1; /* initialize the handle */ sh = semanage_handle_create(); if (sh == NULL) return -1; /* hide error messages */ sh->msg_callback = test_msg_handler; /* use our own policy store */ free(sh->conf->store_path); sh->conf->store_path = strdup("store"); /* initialize paths */ err = semanage_check_init(sh, rootpath); if (err != 0) return -1; return 0; } /* The suite cleanup function. * Returns zero on success, non-zero otherwise. */ int semanage_store_test_cleanup(void) { int err; /* remove the test policy directories */ err = rmdir(modpath); if (err != 0) return -1; err = rmdir(actpath); if (err != 0) return -1; err = rmdir(polpath); if (err != 0) return -1; err = rmdir(rootpath); if (err != 0) return -1; /* cleanup the handle */ semanage_handle_destroy(sh); return 0; } /* Adds all the tests needed for this suite. */ int semanage_store_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "semanage_store_access_check", test_semanage_store_access_check)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "semanage_get_lock", test_semanage_get_lock)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "semanage_nc_sort", test_semanage_nc_sort)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } /* Tests the semanage_store_access_check function in semanage_store.c */ void test_semanage_store_access_check(void) { int err; /* create lock file */ err = mknod(readlockpath, S_IRUSR | S_IWUSR, S_IFREG); /* check with permissions 000 */ err = chmod(modpath, 0); CU_ASSERT(err == 0); err = chmod(readlockpath, 0); CU_ASSERT(err == 0); err = chmod(polpath, 0); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == -1); /* check with permissions 500 */ err = chmod(polpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(readlockpath, S_IRUSR); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == SEMANAGE_CAN_READ); /* check with permissions 700 */ err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(readlockpath, S_IRUSR | S_IWUSR); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == SEMANAGE_CAN_WRITE); /* check with lock file 000 and others 500 */ err = chmod(polpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(readlockpath, 0); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == 0); /* check with lock file 000 and others 700 */ err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(readlockpath, 0); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == 0); /* remove lock file */ err = remove(readlockpath); CU_ASSERT(err == 0); /* check with no lock file and 000 */ err = chmod(modpath, 0); CU_ASSERT(err == 0); err = chmod(polpath, 0); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == -1); /* check with no lock file and 500 */ err = chmod(polpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == 0); /* check with no lock file but write in polpath */ err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == SEMANAGE_CAN_READ); /* check with no lock file and 700 */ err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); CU_ASSERT(err == 0); err = semanage_store_access_check(); CU_ASSERT(err == SEMANAGE_CAN_WRITE); } /* Tests the semanage_get_lock functions in semanage_store.c */ void test_semanage_get_lock(void) { int err; /* attempt to get an active lock */ err = semanage_get_active_lock(sh); CU_ASSERT(err == 0); /* attempt to get the lock again */ err = semanage_get_active_lock(sh); CU_ASSERT(err == 0); /* attempt to release the active lock */ semanage_release_active_lock(sh); /* attempt to get an active lock */ err = semanage_get_active_lock(sh); CU_ASSERT(err == 0); /* attempt to release the active lock */ semanage_release_active_lock(sh); /* attempt to get a trans lock */ err = semanage_get_trans_lock(sh); CU_ASSERT(err == 0); /* attempt to get the lock again */ err = semanage_get_trans_lock(sh); CU_ASSERT(err == 0); /* attempt to release the trans lock */ semanage_release_trans_lock(sh); /* attempt to get a trans lock */ err = semanage_get_trans_lock(sh); CU_ASSERT(err == 0); /* attempt to release the trans lock */ semanage_release_trans_lock(sh); /* remove the lock files */ err = remove(readlockpath); CU_ASSERT(err == 0); err = remove(translockpath); CU_ASSERT(err == 0); } /* Tests the semanage_nc_sort function in semanage_store.c */ void test_semanage_nc_sort(void) { char *source_buf, *sorted_buf = NULL, *good_buf, *bad_buf; size_t source_buf_len, sorted_buf_len, good_buf_len, bad_buf_len; int sourcefd, goodfd, badfd, err; struct stat sb; /* open source file */ sourcefd = open("nc_sort_unsorted", O_RDONLY); if (sourcefd < 0) { CU_FAIL("Missing nc_sort_unsorted test file."); return; } fstat(sourcefd, &sb); source_buf_len = sb.st_size; source_buf = (char *)mmap(NULL, source_buf_len, PROT_READ, MAP_PRIVATE, sourcefd, 0); /* open good result file */ goodfd = open("nc_sort_sorted", O_RDONLY); if (goodfd < 0) { CU_FAIL("Missing nc_sort_sorted test file."); goto out2; } fstat(goodfd, &sb); good_buf_len = sb.st_size; good_buf = (char *)mmap(NULL, good_buf_len, PROT_READ, MAP_PRIVATE, goodfd, 0); /* open malformed source file (missing priorities) */ badfd = open("nc_sort_malformed", O_RDONLY); if (badfd < 0) { CU_FAIL("Missing nc_sort_malformed test file."); goto out1; } fstat(badfd, &sb); bad_buf_len = sb.st_size; bad_buf = (char *)mmap(NULL, bad_buf_len, PROT_READ, MAP_PRIVATE, badfd, 0); /* sort test file */ err = semanage_nc_sort(sh, source_buf, source_buf_len, &sorted_buf, &sorted_buf_len); CU_ASSERT_FALSE(err); CU_ASSERT_STRING_EQUAL(sorted_buf, good_buf); /* reset for reuse in next test */ free(sorted_buf); sorted_buf = NULL; /* sort malformed source file */ err = semanage_nc_sort(sh, bad_buf, bad_buf_len, &sorted_buf, &sorted_buf_len); CU_ASSERT_EQUAL(err, -1); free(sorted_buf); munmap(bad_buf, bad_buf_len); close(badfd); out1: munmap(good_buf, good_buf_len); close(goodfd); out2: munmap(source_buf, source_buf_len); close(sourcefd); } libsemanage/tests/test_semanage_store.h0100644 0000000 0000000 00000002342 13756670064 017441 0ustar000000000 0000000 /* Authors: Christopher Ashworth * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_SEMANAGE_STORE_H__ #define __TEST_SEMANAGE_STORE_H__ #include int semanage_store_test_init(void); int semanage_store_test_cleanup(void); int semanage_store_add_tests(CU_pSuite suite); void test_semanage_store_access_check(void); void test_semanage_get_lock(void); void test_semanage_nc_sort(void); #endif libsemanage/tests/test_utilities.c0100644 0000000 0000000 00000020156 13756670064 016456 0ustar000000000 0000000 /* Authors: Mark Goldman * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* The purpose of this file is to provide unit tests of the functions in: * * libsemanage/src/utilities.c * */ #include #include #include #include #include #include #include #include #include void test_semanage_is_prefix(void); void test_semanage_split_on_space(void); void test_semanage_split(void); void test_semanage_list(void); void test_semanage_str_count(void); void test_semanage_rtrim(void); void test_semanage_str_replace(void); void test_semanage_findval(void); void test_slurp_file_filter(void); char fname[] = { 'T', 'E', 'S', 'T', '_', 'T', 'E', 'M', 'P', '_', 'X', 'X', 'X', 'X', 'X', 'X', '\0' }; int fd; FILE *fptr; int semanage_utilities_test_init(void) { fd = mkstemp(fname); if (fd < 0) { perror("test_semanage_findval: "); CU_FAIL_FATAL ("Error opening temporary file, test cannot start."); } fptr = fdopen(fd, "w+"); if (!fptr) { perror("test_semanage_findval file: "); CU_FAIL_FATAL("Error opening file stream, test cannot start."); } fprintf(fptr, "one\ntwo\nthree\nsigma=foo\n#boo\n#bar\n"); rewind(fptr); return 0; } int semanage_utilities_test_cleanup(void) { unlink(fname); return 0; } int semanage_utilities_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "semanage_is_prefix", test_semanage_is_prefix)) { goto err; } if (NULL == CU_add_test(suite, "semanage_split_on_space", test_semanage_split_on_space)) { goto err; } if (NULL == CU_add_test(suite, "semanage_split", test_semanage_split)) { goto err; } if (NULL == CU_add_test(suite, "semanage_list", test_semanage_list)) { goto err; } if (NULL == CU_add_test(suite, "semanage_str_count", test_semanage_str_count)) { goto err; } if (NULL == CU_add_test(suite, "semanage_rtrim", test_semanage_rtrim)) { goto err; } if (NULL == CU_add_test(suite, "semanage_str_replace", test_semanage_str_replace)) { goto err; } if (NULL == CU_add_test(suite, "semanage_findval", test_semanage_findval)) { goto err; } if (NULL == CU_add_test(suite, "slurp_file_filter", test_slurp_file_filter)) { goto err; } return 0; err: CU_cleanup_registry(); return CU_get_error(); } void test_semanage_is_prefix(void) { const char *str = "some string"; const char *pre = "some"; const char *not_pre = "not this"; CU_ASSERT_TRUE(semanage_is_prefix(str, pre)); CU_ASSERT_TRUE(semanage_is_prefix(str, "")); CU_ASSERT_TRUE(semanage_is_prefix(str, NULL)); CU_ASSERT_FALSE(semanage_is_prefix(str, not_pre)); } void test_semanage_split_on_space(void) { char *str = strdup(" foo bar baz"); char *temp; if (!str) { CU_FAIL ("semanage_split_on_space: unable to perform test, no memory"); } temp = semanage_split_on_space(str); CU_ASSERT_STRING_EQUAL(temp, "bar baz"); free(str); str = temp; temp = semanage_split_on_space(str); CU_ASSERT_STRING_EQUAL(temp, "baz"); free(str); str = temp; temp = semanage_split_on_space(str); CU_ASSERT_STRING_EQUAL(temp, ""); free(str); free(temp); } void test_semanage_split(void) { char *str = strdup("foo1 foo2 foo:bar:"); char *temp; if (!str) { CU_FAIL ("semanage_split_on_space: unable to perform test, no memory"); return; } temp = semanage_split(str, NULL); CU_ASSERT_STRING_EQUAL(temp, "foo2 foo:bar:"); free(str); str = temp; temp = semanage_split(str, ""); CU_ASSERT_STRING_EQUAL(temp, "foo:bar:"); free(str); str = temp; temp = semanage_split(str, ":"); CU_ASSERT_STRING_EQUAL(temp, "bar:"); free(str); str = temp; temp = semanage_split(str, ":"); CU_ASSERT_STRING_EQUAL(temp, ""); free(str); free(temp); } void test_semanage_list(void) { semanage_list_t *list = NULL; semanage_list_t *ptr = NULL; char *temp = NULL; int retval = 0; CU_ASSERT_FALSE(semanage_list_push(&list, "foo")); CU_ASSERT_PTR_NOT_NULL(list); CU_ASSERT_FALSE(semanage_list_push(&list, "bar")); CU_ASSERT_FALSE(semanage_list_push(&list, "gonk")); CU_ASSERT_FALSE(semanage_list_push(&list, "zebra")); for (ptr = list; ptr; ptr = ptr->next) retval++; CU_ASSERT_EQUAL(retval, 4); temp = semanage_list_pop(&list); CU_ASSERT_STRING_EQUAL(temp, "zebra"); CU_ASSERT_FALSE(semanage_list_push(&list, temp)); free(temp); temp = NULL; retval = 0; for (ptr = list; ptr; ptr = ptr->next) retval++; CU_ASSERT_EQUAL(retval, 4); retval = semanage_list_sort(&list); if (retval) { CU_FAIL ("semanage_list_sort: error unrelated to sort (memory?)"); goto past_sort; } CU_ASSERT_STRING_EQUAL(list->data, "bar"); CU_ASSERT_STRING_EQUAL(list->next->data, "foo"); CU_ASSERT_STRING_EQUAL(list->next->next->data, "gonk"); CU_ASSERT_STRING_EQUAL(list->next->next->next->data, "zebra"); past_sort: ptr = semanage_list_find(list, "zebra"); CU_ASSERT_PTR_NOT_NULL(ptr); ptr = semanage_list_find(list, "bogus"); CU_ASSERT_PTR_NULL(ptr); semanage_list_destroy(&list); CU_ASSERT_PTR_NULL(list); } void test_semanage_str_count(void) { const char *test_string = "abaababbaaaba"; CU_ASSERT_EQUAL(semanage_str_count(test_string, 'z'), 0); CU_ASSERT_EQUAL(semanage_str_count(test_string, 'a'), 8); CU_ASSERT_EQUAL(semanage_str_count(test_string, 'b'), 5); } void test_semanage_rtrim(void) { char *str = strdup("/blah/foo/bar/baz/"); CU_ASSERT_PTR_NOT_NULL_FATAL(str); semanage_rtrim(str, 'Q'); CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar/baz/"); semanage_rtrim(str, 'a'); CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar/b"); semanage_rtrim(str, '/'); CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar"); free(str); } void test_semanage_str_replace(void) { const char *test_str = "Hello, I am %{USERNAME} and my id is %{USERID}"; char *str1, *str2; str1 = semanage_str_replace("%{USERNAME}", "root", test_str, 0); CU_ASSERT_STRING_EQUAL(str1, "Hello, I am root and my id is %{USERID}"); str2 = semanage_str_replace("%{USERID}", "0", str1, 1); CU_ASSERT_STRING_EQUAL(str2, "Hello, I am root and my id is 0"); free(str1); free(str2); str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 0); CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(;)"); free(str1); str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 3); CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(:("); free(str1); str1 = semanage_str_replace("", "empty search string", "test", 0); CU_ASSERT_EQUAL(str1, NULL); str1 = semanage_str_replace("a", "", "abracadabra", 0); CU_ASSERT_STRING_EQUAL(str1, "brcdbr"); free(str1); } void test_semanage_findval(void) { char *tok; if (!fptr) { CU_FAIL_FATAL("Temporary file was not created, aborting test."); } tok = semanage_findval(fname, "one", NULL); CU_ASSERT_STRING_EQUAL(tok, ""); free(tok); rewind(fptr); tok = semanage_findval(fname, "one", ""); CU_ASSERT_STRING_EQUAL(tok, ""); free(tok); rewind(fptr); tok = semanage_findval(fname, "sigma", "="); CU_ASSERT_STRING_EQUAL(tok, "foo"); free(tok); } int PREDICATE(const char *str) { return semanage_is_prefix(str, "#"); } void test_slurp_file_filter(void) { semanage_list_t *data, *tmp; int cnt = 0; if (!fptr) { CU_FAIL_FATAL("Temporary file was not created, aborting test."); } rewind(fptr); data = semanage_slurp_file_filter(fptr, PREDICATE); CU_ASSERT_PTR_NOT_NULL_FATAL(data); for (tmp = data; tmp; tmp = tmp->next) cnt++; CU_ASSERT_EQUAL(cnt, 2); semanage_list_destroy(&data); } libsemanage/tests/test_utilities.h0100644 0000000 0000000 00000000240 13756670064 016453 0ustar000000000 0000000 #include int semanage_utilities_test_init(void); int semanage_utilities_test_cleanup(void); int semanage_utilities_add_tests(CU_pSuite suite); libsemanage/tests/utilities.c0100644 0000000 0000000 00000002243 13756670064 015414 0ustar000000000 0000000 /* Authors: Christopher Ashworth * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* The purpose of this file is to provide some functions commonly needed * by our unit tests. */ #include "utilities.h" /* Silence any error output caused by our tests * by using this dummy function to catch messages. */ void test_msg_handler(void *varg, semanage_handle_t * handle, const char *fmt, ...) { } libsemanage/tests/utilities.h0100644 0000000 0000000 00000001716 13756670064 015425 0ustar000000000 0000000 /* Authors: Christopher Ashworth * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "handle.h" void test_msg_handler(void *varg, semanage_handle_t * handle, const char *fmt, ...); libsemanage/utils/0040755 0000000 0000000 00000000000 13756670064 013235 5ustar000000000 0000000 libsemanage/utils/Makefile0100644 0000000 0000000 00000000440 13756670064 014670 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr LIBEXECDIR ?= $(PREFIX)/libexec SELINUXEXECDIR ?= $(LIBEXECDIR)/selinux/ all: install: all -mkdir -p $(DESTDIR)$(SELINUXEXECDIR) install -m 755 semanage_migrate_store $(DESTDIR)$(SELINUXEXECDIR) clean: distclean: clean indent: relabel: libsemanage/utils/semanage_migrate_store0100755 0000000 0000000 00000021773 13756670064 017676 0ustar000000000 0000000 #!/usr/bin/python3 -E from __future__ import print_function import os import errno import shutil import sys from optparse import OptionParser try: import selinux import semanage except ImportError: print("You must install libselinux-python and libsemanage-python before running this tool", file=sys.stderr) exit(1) def copy_file(src, dst): if DEBUG: print("copying %s to %s" % (src, dst)) try: shutil.copy(src, dst) except OSError as the_err: (err, strerr) = the_err.args print("Could not copy %s to %s, %s" % (src, dst, strerr), file=sys.stderr) exit(1) def create_dir(dst, mode): if DEBUG: print("Making directory %s" % dst) try: os.makedirs(dst, mode) except OSError as the_err: (err, stderr) = the_err.args if err == errno.EEXIST: pass else: print("Error creating %s" % dst, file=sys.stderr) exit(1) def create_file(dst): if DEBUG: print("Making file %s" % dst) try: open(dst, 'a').close() except OSError as the_err: (err, stderr) = the_err.args print("Error creating %s" % dst, file=sys.stderr) exit(1) def copy_module(store, name, base): if DEBUG: print("Install module %s" % name) (file, ext) = os.path.splitext(name) if ext != ".pp": # Stray non-pp file in modules directory, skip print("warning: %s has invalid extension, skipping" % name, file=sys.stderr) return try: if base: root = oldstore_path(store) else: root = oldmodules_path(store) bottomdir = bottomdir_path(store) os.mkdir("%s/%s" % (bottomdir, file)) copy_file(os.path.join(root, name), "%s/%s/hll" % (bottomdir, file)) # This is the ext file that will eventually be used to choose a compiler efile = open("%s/%s/lang_ext" % (bottomdir, file), "w+", 0o600) efile.write("pp") efile.close() except (IOError, OSError): print("Error installing module %s" % name, file=sys.stderr) exit(1) def disable_module(file, name, disabledmodules): if DEBUG: print("Disabling %s" % name) (disabledname, disabledext) = os.path.splitext(file) create_file("%s/%s" % (disabledmodules, disabledname)) def migrate_store(store): oldstore = oldstore_path(store) oldmodules = oldmodules_path(store) disabledmodules = disabledmodules_path(store) newstore = newstore_path(store) newmodules = newmodules_path(store) bottomdir = bottomdir_path(store) print("Migrating from %s to %s" % (oldstore, newstore)) # Build up new directory structure create_dir("%s/%s" % (newroot_path(), store), 0o755) create_dir(newstore, 0o700) create_dir(newmodules, 0o700) create_dir(bottomdir, 0o700) create_dir(disabledmodules, 0o700) # Special case for base since it was in a different location copy_module(store, "base.pp", 1) # Dir structure built, start copying files for root, dirs, files in os.walk(oldstore): if root == oldstore: # This is the top level directory, need to move for name in files: # Check to see if it is in TOPPATHS and copy if so if name in TOPPATHS: if name == "seusers": newname = "seusers.local" else: newname = name copy_file(os.path.join(root, name), os.path.join(newstore, newname)) elif root == oldmodules: # This should be the modules directory for name in files: (file, ext) = os.path.splitext(name) if name == "base.pp": print("Error installing module %s, name conflicts with base" % name, file=sys.stderr) exit(1) elif ext == ".disabled": disable_module(file, name, disabledmodules) else: copy_module(store, name, 0) def rebuild_policy(): # Ok, the modules are loaded, lets try to rebuild the policy print("Attempting to rebuild policy from %s" % newroot_path()) curstore = selinux.selinux_getpolicytype()[1] handle = semanage.semanage_handle_create() if not handle: print("Could not create semanage handle", file=sys.stderr) exit(1) semanage.semanage_select_store(handle, curstore, semanage.SEMANAGE_CON_DIRECT) if not semanage.semanage_is_managed(handle): semanage.semanage_handle_destroy(handle) print("SELinux policy is not managed or store cannot be accessed.", file=sys.stderr) exit(1) rc = semanage.semanage_access_check(handle) if rc < semanage.SEMANAGE_CAN_WRITE: semanage.semanage_handle_destroy(handle) print("Cannot write to policy store.", file=sys.stderr) exit(1) rc = semanage.semanage_connect(handle) if rc < 0: semanage.semanage_handle_destroy(handle) print("Could not establish semanage connection", file=sys.stderr) exit(1) semanage.semanage_set_rebuild(handle, 1) rc = semanage.semanage_begin_transaction(handle) if rc < 0: semanage.semanage_handle_destroy(handle) print("Could not begin transaction", file=sys.stderr) exit(1) rc = semanage.semanage_commit(handle) if rc < 0: print("Could not commit transaction", file=sys.stderr) semanage.semanage_handle_destroy(handle) def oldroot_path(): return "%s/etc/selinux" % ROOT def oldstore_path(store): return "%s/%s/modules/active" % (oldroot_path(), store) def oldmodules_path(store): return "%s/modules" % oldstore_path(store) def disabledmodules_path(store): return "%s/disabled" % newmodules_path(store) def newroot_path(): return "%s%s" % (ROOT, PATH) def newstore_path(store): return "%s/%s/active" % (newroot_path(), store) def newmodules_path(store): return "%s/modules" % newstore_path(store) def bottomdir_path(store): return "%s/%s" % (newmodules_path(store), PRIORITY) if __name__ == "__main__": parser = OptionParser() parser.add_option("-p", "--priority", dest="priority", default="100", help="Set priority of modules in new store (default: 100)") parser.add_option("-s", "--store", dest="store", default=None, help="Store to read from and write to") parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="Output debug information") parser.add_option("-c", "--clean", dest="clean", action="store_true", default=False, help="Clean old modules directory after migrate (default: no)") parser.add_option("-n", "--norebuild", dest="norebuild", action="store_true", default=False, help="Disable rebuilding policy after migration (default: no)") parser.add_option("-P", "--path", dest="path", help="Set path for the policy store (default: /var/lib/selinux)") parser.add_option("-r", "--root", dest="root", help="Set an alternative root for the migration (default: /)") (options, args) = parser.parse_args() DEBUG = options.debug PRIORITY = options.priority TYPE = options.store CLEAN = options.clean NOREBUILD = options.norebuild PATH = options.path if PATH is None: PATH = "/var/lib/selinux" ROOT = options.root if ROOT is None: ROOT = "" # List of paths that go in the active 'root' TOPPATHS = [ "commit_num", "ports.local", "interfaces.local", "nodes.local", "booleans.local", "file_contexts.local", "seusers", "users.local", "users_extra", "users_extra.local", "disable_dontaudit", "preserve_tunables", "policy.kern", "file_contexts", "homedir_template", "pkeys.local", "ibendports.local"] create_dir(newroot_path(), 0o755) stores = None if TYPE is not None: stores = [TYPE] else: stores = os.listdir(oldroot_path()) # find stores in oldroot and migrate them to newroot if necessary for store in stores: if not os.path.isdir(oldmodules_path(store)): # already migrated or not an selinux store continue if os.path.isdir(newstore_path(store)): # store has already been migrated, but old modules dir still exits print("warning: Policy type %s has already been migrated, but modules still exist in the old store. Skipping store." % store, file=sys.stderr) continue migrate_store(store) if CLEAN is True: def remove_error(function, path, execinfo): print("warning: Unable to remove old store modules directory %s. Cleaning failed." % oldmodules_path(store), file=sys.stderr) shutil.rmtree(oldmodules_path(store), onerror=remove_error) if NOREBUILD is False: rebuild_policy() libsepol/0040755 0000000 0000000 00000000000 13756670064 011437 5ustar000000000 0000000 libsepol/.gitignore0100644 0000000 0000000 00000000032 13756670064 013417 0ustar000000000 0000000 utils/chkcon libsepol.map libsepol/Android.bp0100644 0000000 0000000 00000005101 13756670064 013334 0ustar000000000 0000000 common_CFLAGS = [ "-D_GNU_SOURCE", "-Wall", "-Werror", "-W", "-Wundef", "-Wshadow", "-Wno-error=missing-noreturn", "-Wmissing-format-attribute", ] cc_library { name: "libsepol", host_supported: true, cflags: common_CFLAGS, srcs: [ "src/assertion.c", "src/avrule_block.c", "src/avtab.c", "src/boolean_record.c", "src/booleans.c", "src/conditional.c", "src/constraint.c", "src/context.c", "src/context_record.c", "src/debug.c", "src/ebitmap.c", "src/expand.c", "src/genbools.c", "src/genusers.c", "src/handle.c", "src/hashtab.c", "src/hierarchy.c", "src/iface_record.c", "src/interfaces.c", "src/kernel_to_cil.c", "src/kernel_to_common.c", "src/kernel_to_conf.c", "src/link.c", "src/mls.c", "src/module.c", "src/module_to_cil.c", "src/node_record.c", "src/nodes.c", "src/polcaps.c", "src/policydb.c", "src/policydb_convert.c", "src/policydb_public.c", "src/port_record.c", "src/ports.c", "src/roles.c", "src/services.c", "src/sidtab.c", "src/symtab.c", "src/user_record.c", "src/users.c", "src/util.c", "src/write.c", "cil/src/android.c", "cil/src/cil_binary.c", "cil/src/cil_build_ast.c", "cil/src/cil.c", "cil/src/cil_copy_ast.c", "cil/src/cil_find.c", "cil/src/cil_fqn.c", "cil/src/cil_lexer.l", "cil/src/cil_list.c", "cil/src/cil_log.c", "cil/src/cil_mem.c", "cil/src/cil_parser.c", "cil/src/cil_policy.c", "cil/src/cil_post.c", "cil/src/cil_reset_ast.c", "cil/src/cil_resolve_ast.c", "cil/src/cil_stack.c", "cil/src/cil_strpool.c", "cil/src/cil_symtab.c", "cil/src/cil_tree.c", "cil/src/cil_verify.c", "cil/src/cil_write_ast.c", ], local_include_dirs: [ "cil/src", "src", ], export_include_dirs: [ "cil/include", "include", ], stl: "none", // The host version of libsepol is loaded by the system python, which does // not have the sanitizer runtimes. target: { host: { sanitize: { never: true, }, }, }, } cc_binary_host { name: "chkcon", srcs: ["utils/chkcon.c"], shared_libs: ["libsepol"], cflags: common_CFLAGS, } libsepol/COPYING0100644 0000000 0000000 00000063500 13756670064 012473 0ustar000000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, 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. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libsepol/Makefile0100644 0000000 0000000 00000000627 13756670064 013101 0ustar000000000 0000000 DISABLE_CIL ?= n export DISABLE_CIL all: $(MAKE) -C src $(MAKE) -C utils install: $(MAKE) -C include install $(MAKE) -C src install $(MAKE) -C utils install $(MAKE) -C man install relabel: $(MAKE) -C src relabel clean: $(MAKE) -C src clean $(MAKE) -C utils clean $(MAKE) -C tests clean indent: $(MAKE) -C src $@ $(MAKE) -C include $@ $(MAKE) -C utils $@ test: $(MAKE) -C tests test libsepol/VERSION0100644 0000000 0000000 00000000004 13756670064 012476 0ustar000000000 0000000 2.9 libsepol/cil/0040755 0000000 0000000 00000000000 13756670064 012206 5ustar000000000 0000000 libsepol/cil/.gitignore0100644 0000000 0000000 00000000171 13756670064 014172 0ustar000000000 0000000 *.swp *.gcda *.gcno *.o *.a src/cil_lexer.c unit_tests cov secilc docs/pdf/ docs/html/ docs/man8/ policy.* file_contexts libsepol/cil/include/0040755 0000000 0000000 00000000000 13756670064 013631 5ustar000000000 0000000 libsepol/cil/include/cil/0040755 0000000 0000000 00000000000 13756670064 014400 5ustar000000000 0000000 libsepol/cil/include/cil/android.h0100644 0000000 0000000 00000003062 13756670064 016167 0ustar000000000 0000000 #ifndef _SEPOL_ANDROID_H_ #define _SEPOL_ANDROID_H_ #include #define PLAT_VERS "curr" #define PLAT_ID "p" #define NON_PLAT_ID "n" /* * cil_android_attrib_mapping - extract attributizable elements of the policy in * srcdb and create the mapping file necessary to link the platform and * non-platform policy files after non-platform policy attributization. * mdb - uninitialized cil_db reference to the resulting policy. Caller * responsibility to destroy. * srcdb - initialized and parsed cil_db reference to source public policy. * num - the version string to append types when converted to attributes. * returns SEPOL_OK if successful, otherwise passes on the encountered error. */ int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const char *num); /* * cil_android_attributize - extract attributizable elements of the policy in * srcdb and convert all usage of those elements in tgtdb to versioned attributes. * Keep the attributes and type definitions so that tgtdb policy is more robust * against future changes to the public policy. * tgtdb - initialized and parsed cil_db reference to modify. * srcdb - initialized and parsed cil_db reference to source public policy * from which to extract attributizable elements. * num - the version string to append types when converted to attributes. * returns SEPOL_OK if successful, otherwise passes on the encountered error. */ int cil_android_attributize(struct cil_db *tgtdb, struct cil_db *srcdb, const char *num); #endif /* _SEPOL_ANDROID_H_ */ libsepol/cil/include/cil/cil.h0100644 0000000 0000000 00000006645 13756670064 015330 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_H_ #define CIL_H_ #include #ifdef __cplusplus extern "C" { #endif struct cil_db; typedef struct cil_db cil_db_t; extern void cil_db_init(cil_db_t **db); extern void cil_db_destroy(cil_db_t **db); extern int cil_add_file(cil_db_t *db, char *name, char *data, size_t size); extern int cil_compile(cil_db_t *db); extern int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db); extern int cil_userprefixes_to_string(cil_db_t *db, char **out, size_t *size); extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size); extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size); extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit); extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls); extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow); extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables); extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown); extern void cil_set_mls(cil_db_t *db, int mls); extern void cil_set_attrs_expand_generated(struct cil_db *db, int attrs_expand_generated); extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_size); extern void cil_set_target_platform(cil_db_t *db, int target_platform); extern void cil_set_policy_version(cil_db_t *db, int policy_version); extern void cil_write_policy_conf(FILE *out, struct cil_db *db); enum cil_log_level { CIL_ERR = 1, CIL_WARN, CIL_INFO }; extern void cil_set_log_level(enum cil_log_level lvl); extern void cil_set_log_handler(void (*handler)(int lvl, char *msg)); #ifdef __GNUC__ __attribute__ ((format(printf, 2, 3))) #endif extern void cil_log(enum cil_log_level lvl, const char *msg, ...); extern void cil_set_malloc_error_handler(void (*handler)(void)); #ifdef __cplusplus } #endif #endif libsepol/cil/include/cil/cil_write_ast.h0100644 0000000 0000000 00000000223 13756670064 017373 0ustar000000000 0000000 #ifndef CIL_WRITE_H_ #define CIL_WRITE_H_ #include int cil_write_ast(struct cil_db *db, const char* path); #endif /* CIL_WRITE_H_ */ libsepol/cil/src/0040755 0000000 0000000 00000000000 13756670064 012775 5ustar000000000 0000000 libsepol/cil/src/android.c0100644 0000000 0000000 00000060212 13756670064 014557 0ustar000000000 0000000 #include #include #include #include #include "cil_build_ast.h" #include "cil_internal.h" #include "cil_strpool.h" #include "cil_symtab.h" #include "cil_tree.h" #define VER_MAP_SZ (1 << 12) /* added to hashmap - currently unused as hashmap is used as a set */ struct version_datum { struct cil_db *db; struct cil_tree_node *ast_node; char *orig_name; }; struct version_args { struct cil_db *db; hashtab_t vers_map; const char *num; }; enum plat_flavor { PLAT_NONE = 0, PLAT_TYPE, PLAT_ATTRIB }; static unsigned int ver_map_hash_val(hashtab_t h, const_hashtab_key_t key) { /* from cil_stpool.c */ char *p, *keyp; size_t size; unsigned int val; val = 0; keyp = (char*)key; size = strlen(keyp); for (p = keyp; ((size_t) (p - keyp)) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (h->size - 1); } static int ver_map_key_cmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { /* hashtab_key_t is just a const char* underneath */ return strcmp(key1, key2); } /* * version_datum pointers all refer to memory owned elsewhere, so just free the * datum itself. */ static int ver_map_entry_destroy(__attribute__ ((unused))hashtab_key_t k, hashtab_datum_t d, __attribute__ ((unused))void *args) { free(d); return 0; } static void ver_map_destroy(hashtab_t h) { hashtab_map(h, ver_map_entry_destroy, NULL); hashtab_destroy(h); } static int __extract_attributees_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct version_args *args = (struct version_args *) extra_args; char *key; struct version_datum *datum; if (node == NULL || finished == NULL || extra_args == NULL) { goto exit; } switch (node->flavor) { case CIL_ROLE: cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", CIL_KEY_ROLE, node->line); rc = SEPOL_ERR; break; case CIL_TYPE: case CIL_TYPEATTRIBUTE: datum = cil_malloc(sizeof(*datum)); datum->db = args->db; datum->ast_node = node; datum->orig_name = DATUM(node->data)->name; key = datum->orig_name; if (!strncmp(key, "base_typeattr_", 14)) { /* checkpolicy creates base attributes which are just typeattributesets, of the existing types and attributes. These may be differnt in every checkpolicy output, ignore them here, they'll be dealt with as a special case when attributizing. */ free(datum); } else { rc = hashtab_insert(args->vers_map, (hashtab_key_t) key, (hashtab_datum_t) datum); if (rc != SEPOL_OK) { goto exit; } } break; case CIL_TYPEALIAS: cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", CIL_KEY_TYPEALIAS, node->line); goto exit; break; case CIL_TYPEPERMISSIVE: cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", CIL_KEY_TYPEPERMISSIVE, node->line); goto exit; break; case CIL_NAMETYPETRANSITION: case CIL_TYPE_RULE: cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", CIL_KEY_TYPETRANSITION, node->line); goto exit; break; default: break; } return SEPOL_OK; exit: return rc; } /* * For the given db, with an already-built AST, fill the vers_map hash table * with every encountered type and attribute. This could eventually be expanded * to include other language constructs, such as users and roles, in which case * multiple hash tables would be needed. These tables can then be used by * attributize() to change all references to these types. */ int cil_extract_attributees(struct cil_db *db, hashtab_t vers_map) { /* walk ast. */ int rc = SEPOL_ERR; struct version_args extra_args; extra_args.db = db; extra_args.vers_map = vers_map; extra_args.num = NULL; rc = cil_tree_walk(db->ast->root, __extract_attributees_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static enum plat_flavor __cil_get_plat_flavor(hashtab_t vers_map, hashtab_key_t key) { enum plat_flavor rc; struct version_datum *vers_datum; vers_datum = (struct version_datum *)hashtab_search(vers_map, key); if (vers_datum == NULL) { return PLAT_NONE; } switch (vers_datum->ast_node->flavor) { case CIL_TYPE: rc = PLAT_TYPE; break; case CIL_TYPEATTRIBUTE: rc = PLAT_ATTRIB; break; default: rc = PLAT_NONE; break; } return rc; } /* * Takes the old name and version string and creates a new strpool entry by * combining them. */ static char *__cil_attrib_get_versname(char *old, const char *vers) { size_t len = 0; char *tmp_new = NULL; char *final; len += strlen(old) + strlen(vers) + 2; tmp_new = cil_malloc(len); snprintf(tmp_new, len, "%s_%s", old, vers); final = cil_strpool_add(tmp_new); free(tmp_new); return final; } /* * Change type to attribute - create new versioned name based on old, create * typeattribute node add to the existing type node. */ static int __cil_attrib_convert_type(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_type *type = (struct cil_type *)node->data; struct cil_typeattribute *typeattr = NULL; struct cil_tree_node *new_ast_node = NULL; char *new_key; cil_typeattribute_init(&typeattr); new_key = __cil_attrib_get_versname(type->datum.name, args->num); /* create new tree node to contain typeattribute and add to tree */ cil_tree_node_init(&new_ast_node); new_ast_node->parent = node->parent; new_ast_node->next = node->next; node->next = new_ast_node; rc = cil_gen_node(args->db, new_ast_node, (struct cil_symtab_datum *) typeattr, new_key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } /* * Update datum - create new key, remove entry under old key, * update entry, and insert under new key */ static int __cil_attrib_swap_symtab_key(struct cil_tree_node *node, char *old_key, const char *num) { int rc = SEPOL_ERR; char *new_key; symtab_t *symtab; struct cil_symtab_datum *datum = (struct cil_symtab_datum *) node->data; new_key = __cil_attrib_get_versname(old_key, num); symtab = datum->symtab; /* TODO: remove, but what happens to other nodes on this datum ?*/ cil_list_remove(datum->nodes, CIL_NODE, node, 0); cil_symtab_remove_datum(datum); rc = cil_symtab_insert(symtab, new_key, datum, node); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } /* * expressions may contains strings which are not in the type-attribute * namespace, so this is not a general cil_expr attributizer. * TODO: add support for other types of expressions which may contain types. */ static int cil_attrib_type_expr(struct cil_list *expr_str, struct version_args *args) { int rc = SEPOL_ERR; struct cil_list_item *curr = NULL; char *new; hashtab_key_t key; /* iterate through cil_list, replacing types */ cil_list_for_each(curr, expr_str) { switch(curr->flavor) { case CIL_LIST: rc = cil_attrib_type_expr((struct cil_list *)curr->data, args); if (rc != SEPOL_OK) goto exit; break; case CIL_STRING: key = (hashtab_key_t) curr->data; enum plat_flavor pf = __cil_get_plat_flavor(args->vers_map, key); if (!strncmp(curr->data, "base_typeattr_", 14) || pf == PLAT_TYPE) { new = __cil_attrib_get_versname((char *) curr->data, args->num); curr->data = (void *) new; } break; case CIL_DATUM: cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n"); rc = SEPOL_ERR; goto exit; break; default: break; } } return SEPOL_OK; exit: return rc; } static int cil_attrib_check_context(struct cil_context *ctxt, struct version_args *args) { int rc = SEPOL_ERR; hashtab_key_t key; if (ctxt->type != NULL) { cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n"); goto exit; } key = (hashtab_key_t) ctxt->type_str; if (__cil_get_plat_flavor(args->vers_map, key) != PLAT_NONE) { /* TODO: reinstate check, but leave out for now cil_log(CIL_ERR, "AST contains context with platform public type: %s\n", ctxt->type_str); rc = SEPOL_ERR; goto exit; */ } return SEPOL_OK; exit: return rc; } static int cil_attrib_sidcontext(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data; if (sidcon->context_str == NULL) { /* sidcon contains an anon context, which needs to have type checked */ rc = cil_attrib_check_context(sidcon->context, args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int cil_attrib_context(struct cil_tree_node *node, struct version_args *args) { struct cil_context *ctxt = (struct cil_context *)node->data; return cil_attrib_check_context(ctxt, args); } static int cil_attrib_roletype(struct cil_tree_node *node, __attribute__((unused)) struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_roletype *roletype = (struct cil_roletype *)node->data; if (roletype->role) { cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n"); goto exit; } key = roletype->type_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { roletype->type_str = __cil_attrib_get_versname(key, args->num); } return SEPOL_OK; exit: return rc; } static int cil_attrib_type(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_type *type = (struct cil_type *)node->data; char *key = type->datum.name; if (type->value) { cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n"); goto exit; } if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { rc = __cil_attrib_convert_type(node, args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int cil_attrib_typepermissive(struct cil_tree_node *node, struct version_args *args __attribute__ ((unused))) { struct cil_typepermissive *typeperm = (struct cil_typepermissive *)node->data; if (typeperm->type != NULL) { cil_log(CIL_ERR, "AST already resolved. ### Not yet supported.\n"); return SEPOL_ERR; } return SEPOL_OK; } static int cil_attrib_typeattribute(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data; char *key = typeattr->datum.name; if (typeattr->types) { cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", node->line); goto exit; } if (!strncmp(key, "base_typeattr_", 14)) { rc = __cil_attrib_swap_symtab_key(node, key, args->num); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int cil_attrib_typeattributeset(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *) node->data; if (typeattrset->datum_expr != NULL) { cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", node->line); goto exit; } key = typeattrset->attr_str; /* first check to see if the attribute to which this set belongs is versioned */ if (!strncmp(key, "base_typeattr_", 14)) { typeattrset->attr_str = __cil_attrib_get_versname(key, args->num); } rc = cil_attrib_type_expr(typeattrset->str_expr, args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static int cil_attrib_typealiasactual(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data; key = aliasact->actual_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) != PLAT_NONE) { cil_log(CIL_ERR, "%s with platform public type not allowed (line %d)\n", CIL_KEY_TYPEALIASACTUAL, node->line); goto exit; } return SEPOL_OK; exit: return rc; } static int cil_attrib_nametypetransition(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_nametypetransition *namettrans = (struct cil_nametypetransition *)node->data; if (namettrans->src != NULL) { cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", node->line); goto exit; } key = namettrans->src_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { namettrans->src_str = __cil_attrib_get_versname(key, args->num); } key = namettrans->tgt_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { namettrans->tgt_str = __cil_attrib_get_versname(key, args->num); } return SEPOL_OK; exit: return rc; } /* * This is exactly the same as cil_attrib_nametypetransition, but the struct * layouts differ, so we can't reuse it. */ static int cil_attrib_type_rule(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_type_rule *type_rule = (struct cil_type_rule *)node->data; if (type_rule->src != NULL) { cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", node->line); goto exit; } key = type_rule->src_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { type_rule->src_str = __cil_attrib_get_versname(key, args->num); } key = type_rule->tgt_str; if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { type_rule->tgt_str = __cil_attrib_get_versname(key, args->num); } return SEPOL_OK; exit: return rc; } static int cil_attrib_avrule(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; char *key; struct cil_avrule *avrule = (struct cil_avrule *)node->data; if (avrule->src != NULL) { cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", node->line); goto exit; } key = avrule->src_str; if (!strncmp(key, "base_typeattr_", 14) || __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { avrule->src_str = __cil_attrib_get_versname(key, args->num); } key = avrule->tgt_str; if (!strncmp(key, "base_typeattr_", 14) || __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { avrule->tgt_str = __cil_attrib_get_versname(key, args->num); } return SEPOL_OK; exit: return rc; } static int cil_attrib_genfscon(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data; if (genfscon->context_str == NULL) { /* genfscon contains an anon context, which needs to have type checked */ rc = cil_attrib_check_context(genfscon->context, args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int cil_attrib_fsuse(struct cil_tree_node *node, struct version_args *args) { int rc = SEPOL_ERR; struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data; if (fsuse->context_str == NULL) { /* fsuse contains an anon context, which needs to have type checked */ rc = cil_attrib_check_context(fsuse->context, args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int __attributize_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct version_args *args = (struct version_args *) extra_args; if (node == NULL || finished == NULL || extra_args == NULL) { goto exit; } switch (node->flavor) { case CIL_SIDCONTEXT: /* contains type, but shouldn't involve an attributized type, maybe add a check on type and error if it conflicts */ rc = cil_attrib_sidcontext(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_ROLE: cil_log(CIL_ERR, "%s declaration illegal non-platform policy (line %d)\n", CIL_KEY_ROLE, node->line); rc = SEPOL_ERR; break; case CIL_ROLETYPE: /* Yes, this is needed if we support roletype in non-platform policy. type_id can be type, typealias or typeattr */ rc = cil_attrib_roletype(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_ROLEATTRIBUTE: /* don't think this is needed, only used for cil_gen_req, and we aren't yet supporting roles in non-platform policy. */ break; case CIL_TYPE: /* conver to attribute if in policy */ rc = cil_attrib_type(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_TYPEPERMISSIVE: rc = cil_attrib_typepermissive(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_TYPEATTRIBUTE: rc = cil_attrib_typeattribute(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_TYPEATTRIBUTESET: rc = cil_attrib_typeattributeset(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_TYPEALIASACTUAL: /* this will break on an attributized type - identify it and throw error */ rc = cil_attrib_typealiasactual(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_NAMETYPETRANSITION: /* not allowed in plat-policy. Types present, throw error if attributee */ rc = cil_attrib_nametypetransition(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_TYPE_RULE: /* not allowed in plat-policy. Types present, throw error if attributee */ rc = cil_attrib_type_rule(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_AVRULE: case CIL_AVRULEX: rc = cil_attrib_avrule(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_CONTEXT: /* not currently found in AOSP policy, but if found would need to be checked to not be attributee */ rc = cil_attrib_context(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_GENFSCON: /* not allowed in plat-policy, but types present, throw error if attributee */ rc = cil_attrib_genfscon(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_FILECON: case CIL_NODECON: case CIL_PORTCON: case CIL_PIRQCON: case CIL_IOMEMCON: case CIL_IOPORTCON: case CIL_PCIDEVICECON: case CIL_DEVICETREECON: case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: case CIL_CALL: case CIL_MACRO: case CIL_OPTIONAL: /* Not currently found in AOSP and not yet properly handled. Return err until support added. */ cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line); rc = SEPOL_ERR; goto exit; case CIL_FSUSE: /* not allowed in plat-policy, but types present, throw error if attributee */ cil_attrib_fsuse(node, args); if (rc != SEPOL_OK) { goto exit; } break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: /* there is type info here, but not sure if we'll allow non-platform code to have this, or whether or not it's in platform policy. Currently assuming that mlsconstrain is private-platform only, and that normal constrain is verboten. */ cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line); rc = SEPOL_ERR; goto exit; default: break; } return SEPOL_OK; exit: return rc; } /* * walk ast, replacing previously identified types and attributes with the * attributized version. Also replace previous references to the attributees * with the versioned type. */ static int cil_attributize(struct cil_db *db, hashtab_t vers_map, const char *num) { int rc = SEPOL_ERR; struct version_args extra_args; extra_args.db = db; extra_args.vers_map = vers_map; extra_args.num = num; rc = cil_tree_walk(db->ast->root, __attributize_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } /* * Create typeattributeset mappings from the attributes generated from the * original types/attributes to the original values. This mapping will provide * the basis for the platform policy's mapping to this public version. * * Add these new typeattributeset nodes to the given cil_db. */ static int cil_build_mappings_tree(hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_typeattributeset *attrset = NULL; struct cil_typeattribute *typeattr = NULL; struct cil_expandtypeattribute *expandattr = NULL; struct cil_tree_node *ast_node = NULL; struct version_args *verargs = (struct version_args *)args; struct cil_tree_node *ast_parent = verargs->db->ast->root; char *orig_type = (char *) k; struct version_datum *vers_datum = (struct version_datum *) d; char *new_key = __cil_attrib_get_versname(orig_type, verargs->num); if (vers_datum->ast_node->flavor == CIL_TYPEATTRIBUTE) { // platform attributes are not versioned return SEPOL_OK; } /* create typeattributeset datum */ cil_typeattributeset_init(&attrset); cil_list_init(&attrset->str_expr, CIL_TYPE); attrset->attr_str = new_key; cil_list_append(attrset->str_expr, CIL_STRING, orig_type); /* create containing tree node */ cil_tree_node_init(&ast_node); ast_node->data = attrset; ast_node->flavor = CIL_TYPEATTRIBUTESET; /* add to tree */ ast_node->parent = ast_parent; if (ast_parent->cl_head == NULL) ast_parent->cl_head = ast_node; else ast_parent->cl_tail->next = ast_node; ast_parent->cl_tail = ast_node; /* create expandtypeattribute datum */ cil_expandtypeattribute_init(&expandattr); cil_list_init(&expandattr->attr_strs, CIL_TYPE); cil_list_append(expandattr->attr_strs, CIL_STRING, new_key); expandattr->expand = CIL_TRUE; /* create containing tree node */ cil_tree_node_init(&ast_node); ast_node->data = expandattr; ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE; /* add to tree */ ast_node->parent = ast_parent; ast_parent->cl_tail->next = ast_node; ast_parent->cl_tail = ast_node; /* re)declare typeattribute. */ cil_typeattribute_init(&typeattr); typeattr->datum.name = new_key; cil_tree_node_init(&ast_node); ast_node->data = typeattr; ast_node->flavor = CIL_TYPEATTRIBUTE; ast_node->parent = ast_parent; ast_parent->cl_tail->next = ast_node; ast_parent->cl_tail = ast_node; return SEPOL_OK; } /* * Initializes the given db and uses the version mapping generated by * cil_extract_attributees() to fill it with the glue policy required to * connect the attributized policy created by cil_attributize() to the policy * declaring the concrete types. */ static int cil_attrib_mapping(struct cil_db **db, hashtab_t vers_map, const char *num) { int rc = SEPOL_ERR; struct version_args extra_args; cil_db_init(db); /* foreach entry in vers_map, create typeattributeset node and attach to tree */ extra_args.db = *db; extra_args.vers_map = NULL; extra_args.num = num; rc = hashtab_map(vers_map, cil_build_mappings_tree, &extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const char *num) { int rc = SEPOL_ERR; hashtab_t ver_map_tab = NULL; ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ); if (!ver_map_tab) { cil_log(CIL_ERR, "Unable to create version mapping table.\n"); goto exit; } rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to build source db AST.\n"); goto exit; } rc = cil_extract_attributees(srcdb, ver_map_tab); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n"); goto exit; } rc = cil_attrib_mapping(mdb, ver_map_tab, num); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to create mapping db from source db.\n"); goto exit; } exit: ver_map_destroy(ver_map_tab); return rc; } int cil_android_attributize(struct cil_db *tgtdb, struct cil_db *srcdb, const char *num) { int rc = SEPOL_ERR; hashtab_t ver_map_tab = NULL; ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ); if (!ver_map_tab) { cil_log(CIL_ERR, "Unable to create version mapping table.\n"); goto exit; } rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to build source db AST.\n"); goto exit; } rc = cil_extract_attributees(srcdb, ver_map_tab); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n"); goto exit; } rc = cil_build_ast(tgtdb, tgtdb->parse->root, tgtdb->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to build target db AST.\n"); goto exit; } rc = cil_attributize(tgtdb, ver_map_tab, num); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to attributize target db.\n"); goto exit; } exit: ver_map_destroy(ver_map_tab); return rc; } libsepol/cil/src/cil.c0100644 0000000 0000000 00000200044 13756670064 013705 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" #include "cil_build_ast.h" #include "cil_parser.h" #include "cil_build_ast.h" #include "cil_resolve_ast.h" #include "cil_fqn.h" #include "cil_post.h" #include "cil_binary.h" #include "cil_policy.h" #include "cil_strpool.h" #include "dso.h" #ifndef DISABLE_SYMVER asm(".symver cil_build_policydb_pdb, cil_build_policydb@LIBSEPOL_1.0"); asm(".symver cil_build_policydb_create_pdb, cil_build_policydb@@LIBSEPOL_1.1"); asm(".symver cil_compile_pdb, cil_compile@LIBSEPOL_1.0"); asm(".symver cil_compile_nopdb, cil_compile@@LIBSEPOL_1.1"); asm(".symver cil_userprefixes_to_string_pdb, cil_userprefixes_to_string@LIBSEPOL_1.0"); asm(".symver cil_userprefixes_to_string_nopdb, cil_userprefixes_to_string@@LIBSEPOL_1.1"); asm(".symver cil_selinuxusers_to_string_pdb, cil_selinuxusers_to_string@LIBSEPOL_1.0"); asm(".symver cil_selinuxusers_to_string_nopdb, cil_selinuxusers_to_string@@LIBSEPOL_1.1"); asm(".symver cil_filecons_to_string_pdb, cil_filecons_to_string@LIBSEPOL_1.0"); asm(".symver cil_filecons_to_string_nopdb, cil_filecons_to_string@@LIBSEPOL_1.1"); #endif int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = { {64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} }; static void cil_init_keys(void) { /* Initialize CIL Keys into strpool */ CIL_KEY_CONS_T1 = cil_strpool_add("t1"); CIL_KEY_CONS_T2 = cil_strpool_add("t2"); CIL_KEY_CONS_T3 = cil_strpool_add("t3"); CIL_KEY_CONS_R1 = cil_strpool_add("r1"); CIL_KEY_CONS_R2 = cil_strpool_add("r2"); CIL_KEY_CONS_R3 = cil_strpool_add("r3"); CIL_KEY_CONS_U1 = cil_strpool_add("u1"); CIL_KEY_CONS_U2 = cil_strpool_add("u2"); CIL_KEY_CONS_U3 = cil_strpool_add("u3"); CIL_KEY_CONS_L1 = cil_strpool_add("l1"); CIL_KEY_CONS_L2 = cil_strpool_add("l2"); CIL_KEY_CONS_H1 = cil_strpool_add("h1"); CIL_KEY_CONS_H2 = cil_strpool_add("h2"); CIL_KEY_AND = cil_strpool_add("and"); CIL_KEY_OR = cil_strpool_add("or"); CIL_KEY_NOT = cil_strpool_add("not"); CIL_KEY_EQ = cil_strpool_add("eq"); CIL_KEY_NEQ = cil_strpool_add("neq"); CIL_KEY_CONS_DOM = cil_strpool_add("dom"); CIL_KEY_CONS_DOMBY = cil_strpool_add("domby"); CIL_KEY_CONS_INCOMP = cil_strpool_add("incomp"); CIL_KEY_CONDTRUE = cil_strpool_add("true"); CIL_KEY_CONDFALSE = cil_strpool_add("false"); CIL_KEY_SELF = cil_strpool_add("self"); CIL_KEY_OBJECT_R = cil_strpool_add("object_r"); CIL_KEY_STAR = cil_strpool_add("*"); CIL_KEY_UDP = cil_strpool_add("udp"); CIL_KEY_TCP = cil_strpool_add("tcp"); CIL_KEY_DCCP = cil_strpool_add("dccp"); CIL_KEY_SCTP = cil_strpool_add("sctp"); CIL_KEY_AUDITALLOW = cil_strpool_add("auditallow"); CIL_KEY_TUNABLEIF = cil_strpool_add("tunableif"); CIL_KEY_ALLOW = cil_strpool_add("allow"); CIL_KEY_DONTAUDIT = cil_strpool_add("dontaudit"); CIL_KEY_TYPETRANSITION = cil_strpool_add("typetransition"); CIL_KEY_TYPECHANGE = cil_strpool_add("typechange"); CIL_KEY_CALL = cil_strpool_add("call"); CIL_KEY_TUNABLE = cil_strpool_add("tunable"); CIL_KEY_XOR = cil_strpool_add("xor"); CIL_KEY_ALL = cil_strpool_add("all"); CIL_KEY_RANGE = cil_strpool_add("range"); CIL_KEY_TYPE = cil_strpool_add("type"); CIL_KEY_ROLE = cil_strpool_add("role"); CIL_KEY_USER = cil_strpool_add("user"); CIL_KEY_USERATTRIBUTE = cil_strpool_add("userattribute"); CIL_KEY_USERATTRIBUTESET = cil_strpool_add("userattributeset"); CIL_KEY_SENSITIVITY = cil_strpool_add("sensitivity"); CIL_KEY_CATEGORY = cil_strpool_add("category"); CIL_KEY_CATSET = cil_strpool_add("categoryset"); CIL_KEY_LEVEL = cil_strpool_add("level"); CIL_KEY_LEVELRANGE = cil_strpool_add("levelrange"); CIL_KEY_CLASS = cil_strpool_add("class"); CIL_KEY_IPADDR = cil_strpool_add("ipaddr"); CIL_KEY_MAP_CLASS = cil_strpool_add("classmap"); CIL_KEY_CLASSPERMISSION = cil_strpool_add("classpermission"); CIL_KEY_BOOL = cil_strpool_add("boolean"); CIL_KEY_STRING = cil_strpool_add("string"); CIL_KEY_NAME = cil_strpool_add("name"); CIL_KEY_HANDLEUNKNOWN = cil_strpool_add("handleunknown"); CIL_KEY_HANDLEUNKNOWN_ALLOW = cil_strpool_add("allow"); CIL_KEY_HANDLEUNKNOWN_DENY = cil_strpool_add("deny"); CIL_KEY_HANDLEUNKNOWN_REJECT = cil_strpool_add("reject"); CIL_KEY_BLOCKINHERIT = cil_strpool_add("blockinherit"); CIL_KEY_BLOCKABSTRACT = cil_strpool_add("blockabstract"); CIL_KEY_CLASSORDER = cil_strpool_add("classorder"); CIL_KEY_CLASSMAPPING = cil_strpool_add("classmapping"); CIL_KEY_CLASSPERMISSIONSET = cil_strpool_add("classpermissionset"); CIL_KEY_COMMON = cil_strpool_add("common"); CIL_KEY_CLASSCOMMON = cil_strpool_add("classcommon"); CIL_KEY_SID = cil_strpool_add("sid"); CIL_KEY_SIDCONTEXT = cil_strpool_add("sidcontext"); CIL_KEY_SIDORDER = cil_strpool_add("sidorder"); CIL_KEY_USERLEVEL = cil_strpool_add("userlevel"); CIL_KEY_USERRANGE = cil_strpool_add("userrange"); CIL_KEY_USERBOUNDS = cil_strpool_add("userbounds"); CIL_KEY_USERPREFIX = cil_strpool_add("userprefix"); CIL_KEY_SELINUXUSER = cil_strpool_add("selinuxuser"); CIL_KEY_SELINUXUSERDEFAULT = cil_strpool_add("selinuxuserdefault"); CIL_KEY_TYPEATTRIBUTE = cil_strpool_add("typeattribute"); CIL_KEY_TYPEATTRIBUTESET = cil_strpool_add("typeattributeset"); CIL_KEY_EXPANDTYPEATTRIBUTE = cil_strpool_add("expandtypeattribute"); CIL_KEY_TYPEALIAS = cil_strpool_add("typealias"); CIL_KEY_TYPEALIASACTUAL = cil_strpool_add("typealiasactual"); CIL_KEY_TYPEBOUNDS = cil_strpool_add("typebounds"); CIL_KEY_TYPEPERMISSIVE = cil_strpool_add("typepermissive"); CIL_KEY_RANGETRANSITION = cil_strpool_add("rangetransition"); CIL_KEY_USERROLE = cil_strpool_add("userrole"); CIL_KEY_ROLETYPE = cil_strpool_add("roletype"); CIL_KEY_ROLETRANSITION = cil_strpool_add("roletransition"); CIL_KEY_ROLEALLOW = cil_strpool_add("roleallow"); CIL_KEY_ROLEATTRIBUTE = cil_strpool_add("roleattribute"); CIL_KEY_ROLEATTRIBUTESET = cil_strpool_add("roleattributeset"); CIL_KEY_ROLEBOUNDS = cil_strpool_add("rolebounds"); CIL_KEY_BOOLEANIF = cil_strpool_add("booleanif"); CIL_KEY_NEVERALLOW = cil_strpool_add("neverallow"); CIL_KEY_TYPEMEMBER = cil_strpool_add("typemember"); CIL_KEY_SENSALIAS = cil_strpool_add("sensitivityalias"); CIL_KEY_SENSALIASACTUAL = cil_strpool_add("sensitivityaliasactual"); CIL_KEY_CATALIAS = cil_strpool_add("categoryalias"); CIL_KEY_CATALIASACTUAL = cil_strpool_add("categoryaliasactual"); CIL_KEY_CATORDER = cil_strpool_add("categoryorder"); CIL_KEY_SENSITIVITYORDER = cil_strpool_add("sensitivityorder"); CIL_KEY_SENSCAT = cil_strpool_add("sensitivitycategory"); CIL_KEY_CONSTRAIN = cil_strpool_add("constrain"); CIL_KEY_MLSCONSTRAIN = cil_strpool_add("mlsconstrain"); CIL_KEY_VALIDATETRANS = cil_strpool_add("validatetrans"); CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans"); CIL_KEY_CONTEXT = cil_strpool_add("context"); CIL_KEY_FILECON = cil_strpool_add("filecon"); CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon"); CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon"); CIL_KEY_PORTCON = cil_strpool_add("portcon"); CIL_KEY_NODECON = cil_strpool_add("nodecon"); CIL_KEY_GENFSCON = cil_strpool_add("genfscon"); CIL_KEY_NETIFCON = cil_strpool_add("netifcon"); CIL_KEY_PIRQCON = cil_strpool_add("pirqcon"); CIL_KEY_IOMEMCON = cil_strpool_add("iomemcon"); CIL_KEY_IOPORTCON = cil_strpool_add("ioportcon"); CIL_KEY_PCIDEVICECON = cil_strpool_add("pcidevicecon"); CIL_KEY_DEVICETREECON = cil_strpool_add("devicetreecon"); CIL_KEY_FSUSE = cil_strpool_add("fsuse"); CIL_KEY_POLICYCAP = cil_strpool_add("policycap"); CIL_KEY_OPTIONAL = cil_strpool_add("optional"); CIL_KEY_DEFAULTUSER = cil_strpool_add("defaultuser"); CIL_KEY_DEFAULTROLE = cil_strpool_add("defaultrole"); CIL_KEY_DEFAULTTYPE = cil_strpool_add("defaulttype"); CIL_KEY_MACRO = cil_strpool_add("macro"); CIL_KEY_IN = cil_strpool_add("in"); CIL_KEY_MLS = cil_strpool_add("mls"); CIL_KEY_DEFAULTRANGE = cil_strpool_add("defaultrange"); CIL_KEY_GLOB = cil_strpool_add("*"); CIL_KEY_FILE = cil_strpool_add("file"); CIL_KEY_DIR = cil_strpool_add("dir"); CIL_KEY_CHAR = cil_strpool_add("char"); CIL_KEY_BLOCK = cil_strpool_add("block"); CIL_KEY_SOCKET = cil_strpool_add("socket"); CIL_KEY_PIPE = cil_strpool_add("pipe"); CIL_KEY_SYMLINK = cil_strpool_add("symlink"); CIL_KEY_ANY = cil_strpool_add("any"); CIL_KEY_XATTR = cil_strpool_add("xattr"); CIL_KEY_TASK = cil_strpool_add("task"); CIL_KEY_TRANS = cil_strpool_add("trans"); CIL_KEY_SOURCE = cil_strpool_add("source"); CIL_KEY_TARGET = cil_strpool_add("target"); CIL_KEY_LOW = cil_strpool_add("low"); CIL_KEY_HIGH = cil_strpool_add("high"); CIL_KEY_LOW_HIGH = cil_strpool_add("low-high"); CIL_KEY_ROOT = cil_strpool_add(""); CIL_KEY_NODE = cil_strpool_add(""); CIL_KEY_PERM = cil_strpool_add("perm"); CIL_KEY_ALLOWX = cil_strpool_add("allowx"); CIL_KEY_AUDITALLOWX = cil_strpool_add("auditallowx"); CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx"); CIL_KEY_NEVERALLOWX = cil_strpool_add("neverallowx"); CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx"); CIL_KEY_IOCTL = cil_strpool_add("ioctl"); CIL_KEY_UNORDERED = cil_strpool_add("unordered"); CIL_KEY_SRC_INFO = cil_strpool_add(""); CIL_KEY_SRC_CIL = cil_strpool_add(""); CIL_KEY_SRC_HLL = cil_strpool_add(""); } void cil_db_init(struct cil_db **db) { *db = cil_malloc(sizeof(**db)); cil_strpool_init(); cil_init_keys(); cil_tree_init(&(*db)->parse); cil_tree_init(&(*db)->ast); cil_root_init((struct cil_root **)&(*db)->ast->root->data); (*db)->sidorder = NULL; (*db)->classorder = NULL; (*db)->catorder = NULL; (*db)->sensitivityorder = NULL; cil_sort_init(&(*db)->netifcon); cil_sort_init(&(*db)->genfscon); cil_sort_init(&(*db)->filecon); cil_sort_init(&(*db)->nodecon); cil_sort_init(&(*db)->ibpkeycon); cil_sort_init(&(*db)->ibendportcon); cil_sort_init(&(*db)->portcon); cil_sort_init(&(*db)->pirqcon); cil_sort_init(&(*db)->iomemcon); cil_sort_init(&(*db)->ioportcon); cil_sort_init(&(*db)->pcidevicecon); cil_sort_init(&(*db)->devicetreecon); cil_sort_init(&(*db)->fsuse); cil_list_init(&(*db)->userprefixes, CIL_LIST_ITEM); cil_list_init(&(*db)->selinuxusers, CIL_LIST_ITEM); cil_list_init(&(*db)->names, CIL_LIST_ITEM); cil_type_init(&(*db)->selftype); (*db)->selftype->datum.name = CIL_KEY_SELF; (*db)->selftype->datum.fqn = CIL_KEY_SELF; (*db)->num_types_and_attrs = 0; (*db)->num_classes = 0; (*db)->num_types = 0; (*db)->num_roles = 0; (*db)->num_users = 0; (*db)->num_cats = 0; (*db)->val_to_type = NULL; (*db)->val_to_role = NULL; (*db)->val_to_user = NULL; (*db)->disable_dontaudit = CIL_FALSE; (*db)->disable_neverallow = CIL_FALSE; (*db)->attrs_expand_generated = CIL_FALSE; (*db)->attrs_expand_size = 1; (*db)->preserve_tunables = CIL_FALSE; (*db)->handle_unknown = -1; (*db)->mls = -1; (*db)->target_platform = SEPOL_TARGET_SELINUX; (*db)->policy_version = POLICYDB_VERSION_MAX; } void cil_db_destroy(struct cil_db **db) { if (db == NULL || *db == NULL) { return; } cil_tree_destroy(&(*db)->parse); cil_tree_destroy(&(*db)->ast); cil_list_destroy(&(*db)->sidorder, CIL_FALSE); cil_list_destroy(&(*db)->classorder, CIL_FALSE); cil_list_destroy(&(*db)->catorder, CIL_FALSE); cil_list_destroy(&(*db)->sensitivityorder, CIL_FALSE); cil_sort_destroy(&(*db)->netifcon); cil_sort_destroy(&(*db)->genfscon); cil_sort_destroy(&(*db)->filecon); cil_sort_destroy(&(*db)->nodecon); cil_sort_destroy(&(*db)->ibpkeycon); cil_sort_destroy(&(*db)->ibendportcon); cil_sort_destroy(&(*db)->portcon); cil_sort_destroy(&(*db)->pirqcon); cil_sort_destroy(&(*db)->iomemcon); cil_sort_destroy(&(*db)->ioportcon); cil_sort_destroy(&(*db)->pcidevicecon); cil_sort_destroy(&(*db)->devicetreecon); cil_sort_destroy(&(*db)->fsuse); cil_list_destroy(&(*db)->userprefixes, CIL_FALSE); cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE); cil_list_destroy(&(*db)->names, CIL_TRUE); cil_destroy_type((*db)->selftype); cil_strpool_destroy(); free((*db)->val_to_type); free((*db)->val_to_role); free((*db)->val_to_user); free(*db); *db = NULL; } void cil_root_init(struct cil_root **root) { struct cil_root *r = cil_malloc(sizeof(*r)); cil_symtab_array_init(r->symtab, cil_sym_sizes[CIL_SYM_ARRAY_ROOT]); *root = r; } void cil_root_destroy(struct cil_root *root) { if (root == NULL) { return; } cil_symtab_array_destroy(root->symtab); free(root); } int cil_add_file(cil_db_t *db, char *name, char *data, size_t size) { char *buffer = NULL; int rc; cil_log(CIL_INFO, "Parsing %s\n", name); buffer = cil_malloc(size + 2); memcpy(buffer, data, size); memset(buffer + size, 0, 2); rc = cil_parser(name, buffer, size + 2, &db->parse); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to parse %s\n", name); goto exit; } free(buffer); buffer = NULL; rc = SEPOL_OK; exit: free(buffer); return rc; } #ifdef DISABLE_SYMVER int cil_compile(struct cil_db *db) #else int cil_compile_nopdb(struct cil_db *db) #endif { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Building AST from Parse Tree\n"); rc = cil_build_ast(db, db->parse->root, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to build ast\n"); goto exit; } cil_log(CIL_INFO, "Destroying Parse Tree\n"); cil_tree_destroy(&db->parse); cil_log(CIL_INFO, "Resolving AST\n"); rc = cil_resolve_ast(db, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to resolve ast\n"); goto exit; } cil_log(CIL_INFO, "Qualifying Names\n"); rc = cil_fqn_qualify(db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to qualify names\n"); goto exit; } cil_log(CIL_INFO, "Compile post process\n"); rc = cil_post_process(db); if (rc != SEPOL_OK ) { cil_log(CIL_INFO, "Post process failed\n"); goto exit; } exit: return rc; } #ifndef DISABLE_SYMVER int cil_compile_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db) { return cil_compile_nopdb(db); } int cil_build_policydb_pdb(cil_db_t *db, sepol_policydb_t *sepol_db) { int rc; cil_log(CIL_INFO, "Building policy binary\n"); rc = cil_binary_create_allocated_pdb(db, sepol_db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to generate binary\n"); goto exit; } exit: return rc; } #endif #ifdef DISABLE_SYMVER int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db) #else int cil_build_policydb_create_pdb(cil_db_t *db, sepol_policydb_t **sepol_db) #endif { int rc; cil_log(CIL_INFO, "Building policy binary\n"); rc = cil_binary_create(db, sepol_db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to generate binary\n"); goto exit; } exit: return rc; } void cil_write_policy_conf(FILE *out, struct cil_db *db) { cil_log(CIL_INFO, "Writing policy.conf file\n"); cil_gen_policy(out, db); } void cil_destroy_data(void **data, enum cil_flavor flavor) { if (*data == NULL) { return; } switch(flavor) { case CIL_NONE: break; case CIL_ROOT: cil_root_destroy(*data); break; case CIL_NODE: break; case CIL_STRING: break; case CIL_DATUM: break; case CIL_LIST: cil_list_destroy(*data, CIL_FALSE); break; case CIL_LIST_ITEM: break; case CIL_PARAM: cil_destroy_param(*data); break; case CIL_ARGS: cil_destroy_args(*data); break; case CIL_BLOCK: cil_destroy_block(*data); break; case CIL_BLOCKINHERIT: cil_destroy_blockinherit(*data); break; case CIL_BLOCKABSTRACT: cil_destroy_blockabstract(*data); break; case CIL_IN: cil_destroy_in(*data); break; case CIL_MACRO: cil_destroy_macro(*data); break; case CIL_CALL: cil_destroy_call(*data); break; case CIL_OPTIONAL: cil_destroy_optional(*data); break; case CIL_BOOL: cil_destroy_bool(*data); break; case CIL_BOOLEANIF: cil_destroy_boolif(*data); break; case CIL_TUNABLE: cil_destroy_tunable(*data); break; case CIL_TUNABLEIF: cil_destroy_tunif(*data); break; case CIL_CONDBLOCK: cil_destroy_condblock(*data); break; case CIL_CONDTRUE: break; case CIL_CONDFALSE: break; case CIL_PERM: case CIL_MAP_PERM: cil_destroy_perm(*data); break; case CIL_COMMON: case CIL_CLASS: case CIL_MAP_CLASS: cil_destroy_class(*data); break; case CIL_CLASSORDER: cil_destroy_classorder(*data); break; case CIL_CLASSPERMISSION: cil_destroy_classpermission(*data); break; case CIL_CLASSCOMMON: cil_destroy_classcommon(*data); break; case CIL_CLASSMAPPING: cil_destroy_classmapping(*data); break; case CIL_CLASSPERMS: cil_destroy_classperms(*data); break; case CIL_CLASSPERMS_SET: cil_destroy_classperms_set(*data); break; case CIL_CLASSPERMISSIONSET: cil_destroy_classpermissionset(*data); break; case CIL_USER: cil_destroy_user(*data); break; case CIL_USERATTRIBUTE: cil_destroy_userattribute(*data); break; case CIL_USERATTRIBUTESET: cil_destroy_userattributeset(*data); break; case CIL_USERPREFIX: cil_destroy_userprefix(*data); break; case CIL_USERROLE: cil_destroy_userrole(*data); break; case CIL_USERLEVEL: cil_destroy_userlevel(*data); break; case CIL_USERRANGE: cil_destroy_userrange(*data); break; case CIL_USERBOUNDS: cil_destroy_bounds(*data); break; case CIL_SELINUXUSER: case CIL_SELINUXUSERDEFAULT: cil_destroy_selinuxuser(*data); break; case CIL_ROLE: cil_destroy_role(*data); break; case CIL_ROLEATTRIBUTE: cil_destroy_roleattribute(*data); break; case CIL_ROLEATTRIBUTESET: cil_destroy_roleattributeset(*data); break; case CIL_ROLETYPE: cil_destroy_roletype(*data); break; case CIL_ROLEBOUNDS: cil_destroy_bounds(*data); break; case CIL_TYPE: cil_destroy_type(*data); break; case CIL_TYPEATTRIBUTE: cil_destroy_typeattribute(*data); break; case CIL_TYPEALIAS: cil_destroy_alias(*data); break; case CIL_TYPEATTRIBUTESET: cil_destroy_typeattributeset(*data); break; case CIL_EXPANDTYPEATTRIBUTE: cil_destroy_expandtypeattribute(*data); break; case CIL_TYPEALIASACTUAL: cil_destroy_aliasactual(*data); break; case CIL_TYPEBOUNDS: cil_destroy_bounds(*data); break; case CIL_TYPEPERMISSIVE: cil_destroy_typepermissive(*data); break; case CIL_SENS: cil_destroy_sensitivity(*data); break; case CIL_SENSALIAS: cil_destroy_alias(*data); break; case CIL_SENSALIASACTUAL: cil_destroy_aliasactual(*data); break; case CIL_SENSITIVITYORDER: cil_destroy_sensitivityorder(*data); break; case CIL_SENSCAT: cil_destroy_senscat(*data); break; case CIL_CAT: cil_destroy_category(*data); break; case CIL_CATSET: cil_destroy_catset(*data); break; case CIL_CATALIAS: cil_destroy_alias(*data); break; case CIL_CATALIASACTUAL: cil_destroy_aliasactual(*data); break; case CIL_CATORDER: cil_destroy_catorder(*data); break; case CIL_LEVEL: cil_destroy_level(*data); break; case CIL_LEVELRANGE: cil_destroy_levelrange(*data); break; case CIL_SID: cil_destroy_sid(*data); break; case CIL_SIDORDER: cil_destroy_sidorder(*data); break; case CIL_NAME: cil_destroy_name(*data); break; case CIL_ROLEALLOW: cil_destroy_roleallow(*data); break; case CIL_AVRULE: case CIL_AVRULEX: cil_destroy_avrule(*data); break; case CIL_PERMISSIONX: cil_destroy_permissionx(*data); break; case CIL_ROLETRANSITION: cil_destroy_roletransition(*data); break; case CIL_TYPE_RULE: cil_destroy_type_rule(*data); break; case CIL_NAMETYPETRANSITION: cil_destroy_typetransition(*data); break; case CIL_RANGETRANSITION: cil_destroy_rangetransition(*data); break; case CIL_CONSTRAIN: cil_destroy_constrain(*data); break; case CIL_MLSCONSTRAIN: cil_destroy_constrain(*data); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: cil_destroy_validatetrans(*data); break; case CIL_CONTEXT: cil_destroy_context(*data); break; case CIL_IPADDR: cil_destroy_ipaddr(*data); break; case CIL_SIDCONTEXT: cil_destroy_sidcontext(*data); break; case CIL_FSUSE: cil_destroy_fsuse(*data); break; case CIL_FILECON: cil_destroy_filecon(*data); break; case CIL_IBPKEYCON: cil_destroy_ibpkeycon(*data); break; case CIL_PORTCON: cil_destroy_portcon(*data); break; case CIL_IBENDPORTCON: cil_destroy_ibendportcon(*data); break; case CIL_NODECON: cil_destroy_nodecon(*data); break; case CIL_GENFSCON: cil_destroy_genfscon(*data); break; case CIL_NETIFCON: cil_destroy_netifcon(*data); break; case CIL_PIRQCON: cil_destroy_pirqcon(*data); break; case CIL_IOMEMCON: cil_destroy_iomemcon(*data); break; case CIL_IOPORTCON: cil_destroy_ioportcon(*data); break; case CIL_PCIDEVICECON: cil_destroy_pcidevicecon(*data); break; case CIL_DEVICETREECON: cil_destroy_devicetreecon(*data); break; case CIL_POLICYCAP: cil_destroy_policycap(*data); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: cil_destroy_default(*data); break; case CIL_DEFAULTRANGE: cil_destroy_defaultrange(*data); break; case CIL_HANDLEUNKNOWN: cil_destroy_handleunknown(*data); break; case CIL_MLS: cil_destroy_mls(*data); break; case CIL_SRC_INFO: cil_destroy_src_info(*data); break; case CIL_OP: case CIL_CONS_OPERAND: break; default: cil_log(CIL_INFO, "Unknown data flavor: %d\n", flavor); break; } *data = NULL; } int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_index) { if (flavor < CIL_MIN_DECLARATIVE) { return SEPOL_ERR; } switch(flavor) { case CIL_BLOCK: *sym_index = CIL_SYM_BLOCKS; break; case CIL_MACRO: *sym_index = CIL_SYM_BLOCKS; break; case CIL_OPTIONAL: *sym_index = CIL_SYM_BLOCKS; break; case CIL_BOOL: *sym_index = CIL_SYM_BOOLS; break; case CIL_TUNABLE: *sym_index = CIL_SYM_TUNABLES; break; case CIL_PERM: case CIL_MAP_PERM: *sym_index = CIL_SYM_PERMS; break; case CIL_COMMON: *sym_index = CIL_SYM_COMMONS; break; case CIL_CLASS: case CIL_MAP_CLASS: *sym_index = CIL_SYM_CLASSES; break; case CIL_CLASSPERMISSION: case CIL_CLASSPERMISSIONSET: *sym_index = CIL_SYM_CLASSPERMSETS; break; case CIL_USER: case CIL_USERATTRIBUTE: *sym_index = CIL_SYM_USERS; break; case CIL_ROLE: case CIL_ROLEATTRIBUTE: *sym_index = CIL_SYM_ROLES; break; case CIL_TYPE: case CIL_TYPEALIAS: case CIL_TYPEATTRIBUTE: *sym_index = CIL_SYM_TYPES; break; case CIL_SENS: case CIL_SENSALIAS: *sym_index = CIL_SYM_SENS; break; case CIL_CAT: case CIL_CATSET: case CIL_CATALIAS: *sym_index = CIL_SYM_CATS; break; case CIL_LEVEL: *sym_index = CIL_SYM_LEVELS; break; case CIL_LEVELRANGE: *sym_index = CIL_SYM_LEVELRANGES; break; case CIL_SID: *sym_index = CIL_SYM_SIDS; break; case CIL_NAME: *sym_index = CIL_SYM_NAMES; break; case CIL_CONTEXT: *sym_index = CIL_SYM_CONTEXTS; break; case CIL_IPADDR: *sym_index = CIL_SYM_IPADDRS; break; case CIL_POLICYCAP: *sym_index = CIL_SYM_POLICYCAPS; break; case CIL_PERMISSIONX: *sym_index = CIL_SYM_PERMX; break; default: *sym_index = CIL_SYM_UNKNOWN; cil_log(CIL_INFO, "Failed to find flavor: %d\n", flavor); return SEPOL_ERR; } return SEPOL_OK; } const char * cil_node_to_string(struct cil_tree_node *node) { switch (node->flavor) { case CIL_NONE: return ""; case CIL_ROOT: return CIL_KEY_ROOT; case CIL_NODE: return CIL_KEY_NODE; case CIL_STRING: return "string"; case CIL_DATUM: return ""; case CIL_LIST: return ""; case CIL_LIST_ITEM: return ""; case CIL_PARAM: return ""; case CIL_ARGS: return ""; case CIL_BLOCK: return CIL_KEY_BLOCK; case CIL_BLOCKINHERIT: return CIL_KEY_BLOCKINHERIT; case CIL_BLOCKABSTRACT: return CIL_KEY_BLOCKABSTRACT; case CIL_IN: return CIL_KEY_IN; case CIL_MACRO: return CIL_KEY_MACRO; case CIL_CALL: return CIL_KEY_CALL; case CIL_OPTIONAL: return CIL_KEY_OPTIONAL; case CIL_BOOL: return CIL_KEY_BOOL; case CIL_BOOLEANIF: return CIL_KEY_BOOLEANIF; case CIL_TUNABLE: return CIL_KEY_TUNABLE; case CIL_TUNABLEIF: return CIL_KEY_TUNABLEIF; case CIL_CONDBLOCK: switch (((struct cil_condblock*)node->data)->flavor) { case CIL_CONDTRUE: return CIL_KEY_CONDTRUE; case CIL_CONDFALSE: return CIL_KEY_CONDFALSE; default: break; } break; case CIL_CONDTRUE: return CIL_KEY_CONDTRUE; case CIL_CONDFALSE: return CIL_KEY_CONDFALSE; case CIL_PERM: return CIL_KEY_PERM; case CIL_COMMON: return CIL_KEY_COMMON; case CIL_CLASS: return CIL_KEY_CLASS; case CIL_CLASSORDER: return CIL_KEY_CLASSORDER; case CIL_MAP_CLASS: return CIL_KEY_MAP_CLASS; case CIL_CLASSPERMISSION: return CIL_KEY_CLASSPERMISSION; case CIL_CLASSCOMMON: return CIL_KEY_CLASSCOMMON; case CIL_CLASSMAPPING: return CIL_KEY_CLASSMAPPING; case CIL_CLASSPERMISSIONSET: return CIL_KEY_CLASSPERMISSIONSET; case CIL_USER: return CIL_KEY_USER; case CIL_USERATTRIBUTE: return CIL_KEY_USERATTRIBUTE; case CIL_USERATTRIBUTESET: return CIL_KEY_USERATTRIBUTESET; case CIL_USERPREFIX: return CIL_KEY_USERPREFIX; case CIL_USERROLE: return CIL_KEY_USERROLE; case CIL_USERLEVEL: return CIL_KEY_USERLEVEL; case CIL_USERRANGE: return CIL_KEY_USERRANGE; case CIL_USERBOUNDS: return CIL_KEY_USERBOUNDS; case CIL_SELINUXUSER: return CIL_KEY_SELINUXUSER; case CIL_SELINUXUSERDEFAULT: return CIL_KEY_SELINUXUSERDEFAULT; case CIL_ROLE: return CIL_KEY_ROLE; case CIL_ROLEATTRIBUTE: return CIL_KEY_ROLEATTRIBUTE; case CIL_ROLEATTRIBUTESET: return CIL_KEY_ROLEATTRIBUTESET; case CIL_ROLETYPE: return CIL_KEY_ROLETYPE; case CIL_ROLEBOUNDS: return CIL_KEY_ROLEBOUNDS; case CIL_TYPE: return CIL_KEY_TYPE; case CIL_TYPEATTRIBUTE: return CIL_KEY_TYPEATTRIBUTE; case CIL_TYPEALIAS: return CIL_KEY_TYPEALIAS; case CIL_TYPEATTRIBUTESET: return CIL_KEY_TYPEATTRIBUTESET; case CIL_EXPANDTYPEATTRIBUTE: return CIL_KEY_EXPANDTYPEATTRIBUTE; case CIL_TYPEALIASACTUAL: return CIL_KEY_TYPEALIASACTUAL; case CIL_TYPEBOUNDS: return CIL_KEY_TYPEBOUNDS; case CIL_TYPEPERMISSIVE: return CIL_KEY_TYPEPERMISSIVE; case CIL_SENS: return CIL_KEY_SENSITIVITY; case CIL_SENSALIAS: return CIL_KEY_SENSALIAS; case CIL_SENSALIASACTUAL: return CIL_KEY_SENSALIASACTUAL; case CIL_SENSITIVITYORDER: return CIL_KEY_SENSITIVITYORDER; case CIL_SENSCAT: return CIL_KEY_SENSCAT; case CIL_CAT: return CIL_KEY_CATEGORY; case CIL_CATSET: return CIL_KEY_CATSET; case CIL_CATALIAS: return CIL_KEY_CATALIAS; case CIL_CATALIASACTUAL: return CIL_KEY_CATALIASACTUAL; case CIL_CATORDER: return CIL_KEY_CATORDER; case CIL_LEVEL: return CIL_KEY_LEVEL; case CIL_LEVELRANGE: return CIL_KEY_LEVELRANGE; case CIL_SID: return CIL_KEY_SID; case CIL_SIDORDER: return CIL_KEY_SIDORDER; case CIL_NAME: return CIL_KEY_NAME; case CIL_ROLEALLOW: return CIL_KEY_ROLEALLOW; case CIL_AVRULE: switch (((struct cil_avrule *)node->data)->rule_kind) { case CIL_AVRULE_ALLOWED: return CIL_KEY_ALLOW; case CIL_AVRULE_AUDITALLOW: return CIL_KEY_AUDITALLOW; case CIL_AVRULE_DONTAUDIT: return CIL_KEY_DONTAUDIT; case CIL_AVRULE_NEVERALLOW: return CIL_KEY_NEVERALLOW; default: break; } break; case CIL_AVRULEX: switch (((struct cil_avrule *)node->data)->rule_kind) { case CIL_AVRULE_ALLOWED: return CIL_KEY_ALLOWX; case CIL_AVRULE_AUDITALLOW: return CIL_KEY_AUDITALLOWX; case CIL_AVRULE_DONTAUDIT: return CIL_KEY_DONTAUDITX; case CIL_AVRULE_NEVERALLOW: return CIL_KEY_NEVERALLOWX; default: break; } break; case CIL_PERMISSIONX: return CIL_KEY_PERMISSIONX; case CIL_ROLETRANSITION: return CIL_KEY_ROLETRANSITION; case CIL_TYPE_RULE: switch (((struct cil_type_rule *)node->data)->rule_kind) { case CIL_TYPE_TRANSITION: return CIL_KEY_TYPETRANSITION; case CIL_TYPE_MEMBER: return CIL_KEY_TYPEMEMBER; case CIL_TYPE_CHANGE: return CIL_KEY_TYPECHANGE; default: break; } break; case CIL_NAMETYPETRANSITION: return CIL_KEY_TYPETRANSITION; case CIL_RANGETRANSITION: return CIL_KEY_RANGETRANSITION; case CIL_CONSTRAIN: return CIL_KEY_CONSTRAIN; case CIL_MLSCONSTRAIN: return CIL_KEY_MLSCONSTRAIN; case CIL_VALIDATETRANS: return CIL_KEY_VALIDATETRANS; case CIL_MLSVALIDATETRANS: return CIL_KEY_MLSVALIDATETRANS; case CIL_CONTEXT: return CIL_KEY_CONTEXT; case CIL_IPADDR: return CIL_KEY_IPADDR; case CIL_SIDCONTEXT: return CIL_KEY_SIDCONTEXT; case CIL_FSUSE: return CIL_KEY_FSUSE; case CIL_FILECON: return CIL_KEY_FILECON; case CIL_IBPKEYCON: return CIL_KEY_IBPKEYCON; case CIL_IBENDPORTCON: return CIL_KEY_IBENDPORTCON; case CIL_PORTCON: return CIL_KEY_PORTCON; case CIL_NODECON: return CIL_KEY_NODECON; case CIL_GENFSCON: return CIL_KEY_GENFSCON; case CIL_NETIFCON: return CIL_KEY_NETIFCON; case CIL_PIRQCON: return CIL_KEY_PIRQCON; case CIL_IOMEMCON: return CIL_KEY_IOMEMCON; case CIL_IOPORTCON: return CIL_KEY_IOPORTCON; case CIL_PCIDEVICECON: return CIL_KEY_PCIDEVICECON; case CIL_DEVICETREECON: return CIL_KEY_DEVICETREECON; case CIL_POLICYCAP: return CIL_KEY_POLICYCAP; case CIL_DEFAULTUSER: return CIL_KEY_DEFAULTUSER; case CIL_DEFAULTROLE: return CIL_KEY_DEFAULTROLE; case CIL_DEFAULTTYPE: return CIL_KEY_DEFAULTTYPE; case CIL_DEFAULTRANGE: return CIL_KEY_DEFAULTRANGE; case CIL_HANDLEUNKNOWN: return CIL_KEY_HANDLEUNKNOWN; case CIL_MLS: return CIL_KEY_MLS; case CIL_SRC_INFO: return CIL_KEY_SRC_INFO; case CIL_ALL: return CIL_KEY_ALL; case CIL_RANGE: return CIL_KEY_RANGE; case CIL_AND: return CIL_KEY_AND; case CIL_OR: return CIL_KEY_OR; case CIL_XOR: return CIL_KEY_XOR; case CIL_NOT: return CIL_KEY_NOT; case CIL_EQ: return CIL_KEY_EQ; case CIL_NEQ: return CIL_KEY_NEQ; case CIL_CONS_DOM: return CIL_KEY_CONS_DOM; case CIL_CONS_DOMBY: return CIL_KEY_CONS_DOMBY; case CIL_CONS_INCOMP: return CIL_KEY_CONS_INCOMP; case CIL_CONS_U1: return CIL_KEY_CONS_U1; case CIL_CONS_U2: return CIL_KEY_CONS_U2; case CIL_CONS_U3: return CIL_KEY_CONS_U3; case CIL_CONS_T1: return CIL_KEY_CONS_T1; case CIL_CONS_T2: return CIL_KEY_CONS_T2; case CIL_CONS_T3: return CIL_KEY_CONS_T3; case CIL_CONS_R1: return CIL_KEY_CONS_R1; case CIL_CONS_R2: return CIL_KEY_CONS_R2; case CIL_CONS_R3: return CIL_KEY_CONS_R3; case CIL_CONS_L1: return CIL_KEY_CONS_L1; case CIL_CONS_L2: return CIL_KEY_CONS_L2; case CIL_CONS_H1: return CIL_KEY_CONS_H1; case CIL_CONS_H2: return CIL_KEY_CONS_H2; default: break; } return ""; } #ifdef DISABLE_SYMVER int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size) #else int cil_userprefixes_to_string_nopdb(struct cil_db *db, char **out, size_t *size) #endif { int rc = SEPOL_ERR; size_t str_len = 0; int buf_pos = 0; char *str_tmp = NULL; struct cil_list_item *curr; struct cil_userprefix *userprefix = NULL; struct cil_user *user = NULL; *out = NULL; if (db->userprefixes->head == NULL) { rc = SEPOL_OK; *size = 0; goto exit; } cil_list_for_each(curr, db->userprefixes) { userprefix = curr->data; user = userprefix->user; str_len += strlen("user ") + strlen(user->datum.fqn) + strlen(" prefix ") + strlen(userprefix->prefix_str) + 2; } *size = str_len * sizeof(char); str_len++; str_tmp = cil_malloc(str_len * sizeof(char)); *out = str_tmp; cil_list_for_each(curr, db->userprefixes) { userprefix = curr->data; user = userprefix->user; buf_pos = snprintf(str_tmp, str_len, "user %s prefix %s;\n", user->datum.fqn, userprefix->prefix_str); str_len -= buf_pos; str_tmp += buf_pos; } rc = SEPOL_OK; exit: return rc; } #ifndef DISABLE_SYMVER int cil_userprefixes_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) { return cil_userprefixes_to_string_nopdb(db, out, size); } #endif static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitmap) { int rc = SEPOL_ERR; struct cil_list_item *i; struct cil_list_item *j; struct cil_cat* cat; struct cil_catset *cs; struct cil_tree_node *node; if (cats == NULL) { rc = SEPOL_OK; goto exit; } cil_list_for_each(i, cats->datum_expr) { node = DATUM(i->data)->nodes->head->data; if (node->flavor == CIL_CATSET) { cs = (struct cil_catset*)i->data; cil_list_for_each(j, cs->cats->datum_expr) { cat = (struct cil_cat*)j->data; rc = ebitmap_set_bit(cats_ebitmap, cat->value, 1); if (rc != SEPOL_OK) { goto exit; } } } else { cat = (struct cil_cat*)i->data; rc = ebitmap_set_bit(cats_ebitmap, cat->value, 1); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int cil_level_equals(struct cil_level *low, struct cil_level *high) { int rc; struct ebitmap elow; struct ebitmap ehigh; if (strcmp(low->sens->datum.fqn, high->sens->datum.fqn)) { rc = 0; goto exit; } ebitmap_init(&elow); ebitmap_init(&ehigh); rc = cil_cats_to_ebitmap(low->cats, &elow); if (rc != SEPOL_OK) { goto exit; } rc = cil_cats_to_ebitmap(high->cats, &ehigh); if (rc != SEPOL_OK) { goto exit; } rc = ebitmap_cmp(&elow, &ehigh); ebitmap_destroy(&elow); ebitmap_destroy(&ehigh); exit: return rc; } static int __cil_level_strlen(struct cil_level *lvl) { struct cil_list_item *item; struct cil_cats *cats = lvl->cats; int str_len = 0; char *str1 = NULL; char *str2 = NULL; int first = -1; int last = -1; str_len += strlen(lvl->sens->datum.fqn); if (cats && cats->datum_expr != NULL) { str_len++; /* initial ":" */ cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; str2 = cat->datum.fqn; } else { if (first == last) { str_len += strlen(str1) + strlen(cat->datum.fqn) + 1; } else if (last == first + 1) { str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } else { str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } first = -1; last = -1; if (item->next != NULL) { str_len++; /* space for "," after */ } } } if (first != -1) { if (first == last) { str_len += strlen(str1); } else if (last == first + 1) { str_len += strlen(str1) + strlen(str2) + 1; } else { str_len += strlen(str1) + strlen(str2) + 1; } } } return str_len; } static int __cil_level_to_string(struct cil_level *lvl, char *out) { struct cil_list_item *item; struct cil_cats *cats = lvl->cats; int buf_pos = 0; char *str_tmp = out; char *str1 = NULL; char *str2 = NULL; int first = -1; int last = -1; buf_pos = sprintf(str_tmp, "%s", lvl->sens->datum.fqn); str_tmp += buf_pos; if (cats && cats->datum_expr != NULL) { buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; str2 = cat->datum.fqn; } else { if (first == last) { buf_pos = sprintf(str_tmp, "%s,%s", str1, cat->datum.fqn); str_tmp += buf_pos; } else if (last == first + 1) { buf_pos = sprintf(str_tmp, "%s,%s,%s", str1, str2, cat->datum.fqn); str_tmp += buf_pos; } else { buf_pos = sprintf(str_tmp, "%s.%s,%s",str1, str2, cat->datum.fqn); str_tmp += buf_pos; } first = -1; last = -1; if (item->next != NULL) { buf_pos = sprintf(str_tmp, ","); str_tmp += buf_pos; } } } if (first != -1) { if (first == last) { buf_pos = sprintf(str_tmp, "%s", str1); str_tmp += buf_pos; } else if (last == first + 1) { buf_pos = sprintf(str_tmp, "%s,%s", str1, str2); str_tmp += buf_pos; } else { buf_pos = sprintf(str_tmp, "%s.%s",str1, str2); str_tmp += buf_pos; } } } return str_tmp - out; } #ifdef DISABLE_SYMVER int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size) #else int cil_selinuxusers_to_string_nopdb(struct cil_db *db, char **out, size_t *size) #endif { size_t str_len = 0; int buf_pos = 0; char *str_tmp = NULL; struct cil_list_item *curr; if (db->selinuxusers->head == NULL) { *size = 0; *out = NULL; return SEPOL_OK; } cil_list_for_each(curr, db->selinuxusers) { struct cil_selinuxuser *selinuxuser = curr->data; struct cil_user *user = selinuxuser->user; str_len += strlen(selinuxuser->name_str) + strlen(user->datum.fqn) + 1; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = selinuxuser->range; str_len += __cil_level_strlen(range->low) + __cil_level_strlen(range->high) + 2; } str_len++; } *size = str_len * sizeof(char); str_tmp = cil_malloc(*size+1); *out = str_tmp; for(curr = db->selinuxusers->head; curr != NULL; curr = curr->next) { struct cil_selinuxuser *selinuxuser = curr->data; struct cil_user *user = selinuxuser->user; buf_pos = sprintf(str_tmp, "%s:%s", selinuxuser->name_str, user->datum.fqn); str_tmp += buf_pos; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = selinuxuser->range; buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->low, str_tmp); str_tmp += buf_pos; buf_pos = sprintf(str_tmp, "-"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->high, str_tmp); str_tmp += buf_pos; } buf_pos = sprintf(str_tmp, "\n"); str_tmp += buf_pos; } return SEPOL_OK; } #ifndef DISABLE_SYMVER int cil_selinuxusers_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) { return cil_selinuxusers_to_string_nopdb(db, out, size); } #endif #ifdef DISABLE_SYMVER int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size) #else int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size) #endif { uint32_t i = 0; int buf_pos = 0; size_t str_len = 0; char *str_tmp = NULL; struct cil_sort *filecons = db->filecon; for (i = 0; i < filecons->count; i++) { struct cil_filecon *filecon = filecons->array[i]; struct cil_context *ctx = filecon->context; str_len += strlen(filecon->path_str); if (filecon->type != CIL_FILECON_ANY) { /* If a type is specified, +2 for type string, +1 for tab */ str_len += 3; } if (ctx != NULL) { struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; str_len += (strlen(user->datum.fqn) + strlen(role->datum.fqn) + strlen(type->datum.fqn) + 3); if (db->mls == CIL_TRUE) { struct cil_levelrange *range = ctx->range; if (cil_level_equals(range->low, range->high)) { str_len += __cil_level_strlen(range->low) + 1; } else { str_len += __cil_level_strlen(range->low) + __cil_level_strlen(range->high) + 2; } } } else { str_len += strlen("\t<>"); } str_len++; } *size = str_len * sizeof(char); str_tmp = cil_malloc(*size+1); *out = str_tmp; for (i = 0; i < filecons->count; i++) { struct cil_filecon *filecon = filecons->array[i]; struct cil_context *ctx = filecon->context; const char *str_type = NULL; buf_pos = sprintf(str_tmp, "%s", filecon->path_str); str_tmp += buf_pos; switch(filecon->type) { case CIL_FILECON_FILE: str_type = "\t--"; break; case CIL_FILECON_DIR: str_type = "\t-d"; break; case CIL_FILECON_CHAR: str_type = "\t-c"; break; case CIL_FILECON_BLOCK: str_type = "\t-b"; break; case CIL_FILECON_SOCKET: str_type = "\t-s"; break; case CIL_FILECON_PIPE: str_type = "\t-p"; break; case CIL_FILECON_SYMLINK: str_type = "\t-l"; break; default: str_type = ""; break; } buf_pos = sprintf(str_tmp, "%s", str_type); str_tmp += buf_pos; if (ctx != NULL) { struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; buf_pos = sprintf(str_tmp, "\t%s:%s:%s", user->datum.fqn, role->datum.fqn, type->datum.fqn); str_tmp += buf_pos; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = ctx->range; buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->low, str_tmp); str_tmp += buf_pos; if (!cil_level_equals(range->low, range->high)) { buf_pos = sprintf(str_tmp, "-"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->high, str_tmp); str_tmp += buf_pos; } } } else { buf_pos = sprintf(str_tmp, "\t<>"); str_tmp += buf_pos; } buf_pos = sprintf(str_tmp, "\n"); str_tmp += buf_pos; } return SEPOL_OK; } #ifndef DISABLE_SYMVER int cil_filecons_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) { return cil_filecons_to_string_nopdb(db, out, size); } #endif void cil_set_disable_dontaudit(struct cil_db *db, int disable_dontaudit) { db->disable_dontaudit = disable_dontaudit; } void cil_set_disable_neverallow(struct cil_db *db, int disable_neverallow) { db->disable_neverallow = disable_neverallow; } void cil_set_attrs_expand_generated(struct cil_db *db, int attrs_expand_generated) { db->attrs_expand_generated = attrs_expand_generated; } void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_size) { db->attrs_expand_size = attrs_expand_size; } void cil_set_preserve_tunables(struct cil_db *db, int preserve_tunables) { db->preserve_tunables = preserve_tunables; } int cil_set_handle_unknown(struct cil_db *db, int handle_unknown) { int rc = 0; switch (handle_unknown) { case SEPOL_DENY_UNKNOWN: case SEPOL_REJECT_UNKNOWN: case SEPOL_ALLOW_UNKNOWN: db->handle_unknown = handle_unknown; break; default: cil_log(CIL_ERR, "Unknown value for handle-unknown: %i\n", handle_unknown); rc = -1; } return rc; } void cil_set_mls(struct cil_db *db, int mls) { db->mls = mls; } void cil_set_multiple_decls(struct cil_db *db, int multiple_decls) { db->multiple_decls = multiple_decls; } void cil_set_target_platform(struct cil_db *db, int target_platform) { db->target_platform = target_platform; } void cil_set_policy_version(struct cil_db *db, int policy_version) { db->policy_version = policy_version; } void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]) { uint32_t i = 0; for (i = 0; i < CIL_SYM_NUM; i++) { cil_symtab_init(&symtab[i], symtab_sizes[i]); } } void cil_symtab_array_destroy(symtab_t symtab[]) { int i = 0; for (i = 0; i < CIL_SYM_NUM; i++) { cil_symtab_destroy(&symtab[i]); } } void cil_destroy_ast_symtabs(struct cil_tree_node *current) { while (current) { switch (current->flavor) { case CIL_BLOCK: cil_symtab_array_destroy(((struct cil_block*)current->data)->symtab); break; case CIL_IN: cil_symtab_array_destroy(((struct cil_in*)current->data)->symtab); break; case CIL_CLASS: case CIL_COMMON: case CIL_MAP_CLASS: cil_symtab_destroy(&((struct cil_class*)current->data)->perms); break; case CIL_MACRO: cil_symtab_array_destroy(((struct cil_macro*)current->data)->symtab); break; case CIL_CONDBLOCK: cil_symtab_array_destroy(((struct cil_condblock*)current->data)->symtab); break; default: break; } if (current->cl_head) { cil_destroy_ast_symtabs(current->cl_head); } current = current->next; } } int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index) { struct cil_tree_node *node = ast_node; *symtab = NULL; if (sym_index == CIL_SYM_PERMS) { /* Class statements are not blocks, so the passed node should be the class */ if (node->flavor == CIL_CLASS || node->flavor == CIL_MAP_CLASS || node->flavor == CIL_COMMON) { *symtab = &((struct cil_class*)node->data)->perms; return SEPOL_OK; } goto exit; } if (sym_index < CIL_SYM_BLOCKS || sym_index >= CIL_SYM_NUM) { cil_log(CIL_ERR, "Invalid symtab type\n"); goto exit; } while (node != NULL && *symtab == NULL) { switch (node->flavor) { case CIL_ROOT: *symtab = &((struct cil_root *)node->data)->symtab[sym_index]; break; case CIL_BLOCK: *symtab = &((struct cil_block*)node->data)->symtab[sym_index]; break; case CIL_MACRO: *symtab = &((struct cil_macro*)node->data)->symtab[sym_index]; break; case CIL_IN: /* In blocks only exist before resolving the AST */ *symtab = &((struct cil_in*)node->data)->symtab[sym_index]; break; case CIL_CONDBLOCK: { if (node->parent->flavor == CIL_TUNABLEIF) { /* Cond blocks only exist before resolving the AST */ *symtab = &((struct cil_condblock*)node->data)->symtab[sym_index]; } else if (node->parent->flavor == CIL_BOOLEANIF) { node = node->parent->parent; } break; } default: node = node->parent; } } if (*symtab == NULL) { goto exit; } return SEPOL_OK; exit: cil_tree_log(ast_node, CIL_ERR, "Failed to get symtab from node"); return SEPOL_ERR; } void cil_sort_init(struct cil_sort **sort) { *sort = cil_malloc(sizeof(**sort)); (*sort)->flavor = CIL_NONE; (*sort)->count = 0; (*sort)->index = 0; (*sort)->array = NULL; } void cil_sort_destroy(struct cil_sort **sort) { (*sort)->flavor = CIL_NONE; (*sort)->count = 0; (*sort)->index = 0; if ((*sort)->array != NULL) { free((*sort)->array); } (*sort)->array = NULL; free(*sort); *sort = NULL; } void cil_netifcon_init(struct cil_netifcon **netifcon) { *netifcon = cil_malloc(sizeof(**netifcon)); (*netifcon)->interface_str = NULL; (*netifcon)->if_context_str = NULL; (*netifcon)->if_context = NULL; (*netifcon)->packet_context_str = NULL; (*netifcon)->packet_context = NULL; (*netifcon)->context_str = NULL; } void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon) { *ibendportcon = cil_malloc(sizeof(**ibendportcon)); (*ibendportcon)->dev_name_str = NULL; (*ibendportcon)->port = 0; (*ibendportcon)->context_str = NULL; (*ibendportcon)->context = NULL; } void cil_context_init(struct cil_context **context) { *context = cil_malloc(sizeof(**context)); cil_symtab_datum_init(&(*context)->datum); (*context)->user_str = NULL; (*context)->user = NULL; (*context)->role_str = NULL; (*context)->role = NULL; (*context)->type_str = NULL; (*context)->type = NULL; (*context)->range_str = NULL; (*context)->range = NULL; } void cil_level_init(struct cil_level **level) { *level = cil_malloc(sizeof(**level)); cil_symtab_datum_init(&(*level)->datum); (*level)->sens_str = NULL; (*level)->sens = NULL; (*level)->cats = NULL; } void cil_levelrange_init(struct cil_levelrange **range) { *range = cil_malloc(sizeof(**range)); cil_symtab_datum_init(&(*range)->datum); (*range)->low_str = NULL; (*range)->low = NULL; (*range)->high_str = NULL; (*range)->high = NULL; } void cil_sens_init(struct cil_sens **sens) { *sens = cil_malloc(sizeof(**sens)); cil_symtab_datum_init(&(*sens)->datum); (*sens)->cats_list = NULL; (*sens)->ordered = CIL_FALSE; } void cil_block_init(struct cil_block **block) { *block = cil_malloc(sizeof(**block)); cil_symtab_datum_init(&(*block)->datum); cil_symtab_array_init((*block)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK]); (*block)->is_abstract = CIL_FALSE; (*block)->bi_nodes = NULL; } void cil_blockinherit_init(struct cil_blockinherit **inherit) { *inherit = cil_malloc(sizeof(**inherit)); (*inherit)->block_str = NULL; (*inherit)->block = NULL; } void cil_blockabstract_init(struct cil_blockabstract **abstract) { *abstract = cil_malloc(sizeof(**abstract)); (*abstract)->block_str = NULL; } void cil_in_init(struct cil_in **in) { *in = cil_malloc(sizeof(**in)); cil_symtab_array_init((*in)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_IN]); (*in)->block_str = NULL; } void cil_class_init(struct cil_class **class) { *class = cil_malloc(sizeof(**class)); cil_symtab_datum_init(&(*class)->datum); cil_symtab_init(&(*class)->perms, CIL_CLASS_SYM_SIZE); (*class)->num_perms = 0; (*class)->common = NULL; (*class)->ordered = CIL_FALSE; } void cil_classorder_init(struct cil_classorder **classorder) { *classorder = cil_malloc(sizeof(**classorder)); (*classorder)->class_list_str = NULL; } void cil_classcommon_init(struct cil_classcommon **classcommon) { *classcommon = cil_malloc(sizeof(**classcommon)); (*classcommon)->class_str = NULL; (*classcommon)->common_str = NULL; } void cil_sid_init(struct cil_sid **sid) { *sid = cil_malloc(sizeof(**sid)); cil_symtab_datum_init(&(*sid)->datum); (*sid)->ordered = CIL_FALSE; (*sid)->context = NULL; } void cil_sidcontext_init(struct cil_sidcontext **sidcontext) { *sidcontext = cil_malloc(sizeof(**sidcontext)); (*sidcontext)->sid_str = NULL; (*sidcontext)->context_str = NULL; (*sidcontext)->context = NULL; } void cil_sidorder_init(struct cil_sidorder **sidorder) { *sidorder = cil_malloc(sizeof(**sidorder)); (*sidorder)->sid_list_str = NULL; } void cil_userrole_init(struct cil_userrole **userrole) { *userrole = cil_malloc(sizeof(**userrole)); (*userrole)->user_str = NULL; (*userrole)->user = NULL; (*userrole)->role_str = NULL; (*userrole)->role = NULL; } void cil_userprefix_init(struct cil_userprefix **userprefix) { *userprefix = cil_malloc(sizeof(**userprefix)); (*userprefix)->user_str = NULL; (*userprefix)->user = NULL; (*userprefix)->prefix_str = NULL; } void cil_selinuxuser_init(struct cil_selinuxuser **selinuxuser) { *selinuxuser = cil_malloc(sizeof(**selinuxuser)); (*selinuxuser)->name_str = NULL; (*selinuxuser)->user_str = NULL; (*selinuxuser)->user = NULL; (*selinuxuser)->range_str = NULL; (*selinuxuser)->range = NULL; } void cil_roletype_init(struct cil_roletype **roletype) { *roletype = cil_malloc(sizeof(**roletype)); (*roletype)->role_str = NULL; (*roletype)->role = NULL; (*roletype)->type_str = NULL; (*roletype)->type = NULL; } void cil_roleattribute_init(struct cil_roleattribute **attr) { *attr = cil_malloc(sizeof(**attr)); cil_symtab_datum_init(&(*attr)->datum); (*attr)->expr_list = NULL; (*attr)->roles = NULL; } void cil_roleattributeset_init(struct cil_roleattributeset **attrset) { *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_typeattribute_init(struct cil_typeattribute **attr) { *attr = cil_malloc(sizeof(**attr)); cil_symtab_datum_init(&(*attr)->datum); (*attr)->expr_list = NULL; (*attr)->types = NULL; (*attr)->used = CIL_FALSE; (*attr)->keep = CIL_FALSE; } void cil_typeattributeset_init(struct cil_typeattributeset **attrset) { *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_expandtypeattribute_init(struct cil_expandtypeattribute **expandattr) { *expandattr = cil_malloc(sizeof(**expandattr)); (*expandattr)->attr_strs = NULL; (*expandattr)->attr_datums = NULL; (*expandattr)->expand = 0; } void cil_alias_init(struct cil_alias **alias) { *alias = cil_malloc(sizeof(**alias)); (*alias)->actual = NULL; cil_symtab_datum_init(&(*alias)->datum); } void cil_aliasactual_init(struct cil_aliasactual **aliasactual) { *aliasactual = cil_malloc(sizeof(**aliasactual)); (*aliasactual)->alias_str = NULL; (*aliasactual)->actual_str = NULL; } void cil_typepermissive_init(struct cil_typepermissive **typeperm) { *typeperm = cil_malloc(sizeof(**typeperm)); (*typeperm)->type_str = NULL; (*typeperm)->type = NULL; } void cil_name_init(struct cil_name **name) { *name = cil_malloc(sizeof(**name)); cil_symtab_datum_init(&(*name)->datum); (*name)->name_str = NULL; } void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans) { *nametypetrans = cil_malloc(sizeof(**nametypetrans)); (*nametypetrans)->src_str = NULL; (*nametypetrans)->src = NULL; (*nametypetrans)->tgt_str = NULL; (*nametypetrans)->tgt = NULL; (*nametypetrans)->obj_str = NULL; (*nametypetrans)->obj = NULL; (*nametypetrans)->name_str = NULL; (*nametypetrans)->name = NULL; (*nametypetrans)->result_str = NULL; (*nametypetrans)->result = NULL; } void cil_rangetransition_init(struct cil_rangetransition **rangetrans) { *rangetrans = cil_malloc(sizeof(**rangetrans)); (*rangetrans)->src_str = NULL; (*rangetrans)->src = NULL; (*rangetrans)->exec_str = NULL; (*rangetrans)->exec = NULL; (*rangetrans)->obj_str = NULL; (*rangetrans)->obj = NULL; (*rangetrans)->range_str = NULL; (*rangetrans)->range = NULL; } void cil_bool_init(struct cil_bool **cilbool) { *cilbool = cil_malloc(sizeof(**cilbool)); cil_symtab_datum_init(&(*cilbool)->datum); (*cilbool)->value = 0; } void cil_tunable_init(struct cil_tunable **ciltun) { *ciltun = cil_malloc(sizeof(**ciltun)); cil_symtab_datum_init(&(*ciltun)->datum); (*ciltun)->value = 0; } void cil_condblock_init(struct cil_condblock **cb) { *cb = cil_malloc(sizeof(**cb)); (*cb)->flavor = CIL_NONE; cil_symtab_array_init((*cb)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_CONDBLOCK]); } void cil_boolif_init(struct cil_booleanif **bif) { *bif = cil_malloc(sizeof(**bif)); (*bif)->str_expr = NULL; (*bif)->datum_expr = NULL; } void cil_tunif_init(struct cil_tunableif **tif) { *tif = cil_malloc(sizeof(**tif)); (*tif)->str_expr = NULL; (*tif)->datum_expr = NULL; } void cil_avrule_init(struct cil_avrule **avrule) { *avrule = cil_malloc(sizeof(**avrule)); (*avrule)->is_extended = 0; (*avrule)->rule_kind = CIL_NONE; (*avrule)->src_str = NULL; (*avrule)->src = NULL; (*avrule)->tgt_str = NULL; (*avrule)->tgt = NULL; memset(&((*avrule)->perms), 0, sizeof((*avrule)->perms)); } void cil_permissionx_init(struct cil_permissionx **permx) { *permx = cil_malloc(sizeof(**permx)); cil_symtab_datum_init(&(*permx)->datum); (*permx)->kind = CIL_NONE; (*permx)->obj_str = NULL; (*permx)->obj = NULL; (*permx)->expr_str = NULL; (*permx)->perms = NULL; } void cil_type_rule_init(struct cil_type_rule **type_rule) { *type_rule = cil_malloc(sizeof(**type_rule)); (*type_rule)->rule_kind = CIL_NONE; (*type_rule)->src_str = NULL; (*type_rule)->src = NULL; (*type_rule)->tgt_str = NULL; (*type_rule)->tgt = NULL; (*type_rule)->obj_str = NULL; (*type_rule)->obj = NULL; (*type_rule)->result_str = NULL; (*type_rule)->result = NULL; } void cil_roletransition_init(struct cil_roletransition **role_trans) { *role_trans = cil_malloc(sizeof(**role_trans)); (*role_trans)->src_str = NULL; (*role_trans)->src = NULL; (*role_trans)->tgt_str = NULL; (*role_trans)->tgt = NULL; (*role_trans)->obj_str = NULL; (*role_trans)->obj = NULL; (*role_trans)->result_str = NULL; (*role_trans)->result = NULL; } void cil_roleallow_init(struct cil_roleallow **roleallow) { *roleallow = cil_malloc(sizeof(**roleallow)); (*roleallow)->src_str = NULL; (*roleallow)->src = NULL; (*roleallow)->tgt_str = NULL; (*roleallow)->tgt = NULL; } void cil_catset_init(struct cil_catset **catset) { *catset = cil_malloc(sizeof(**catset)); cil_symtab_datum_init(&(*catset)->datum); (*catset)->cats = NULL; } void cil_senscat_init(struct cil_senscat **senscat) { *senscat = cil_malloc(sizeof(**senscat)); (*senscat)->sens_str = NULL; (*senscat)->cats = NULL; } void cil_cats_init(struct cil_cats **cats) { *cats = cil_malloc(sizeof(**cats)); (*cats)->evaluated = CIL_FALSE; (*cats)->str_expr = NULL; (*cats)->datum_expr = NULL; } void cil_filecon_init(struct cil_filecon **filecon) { *filecon = cil_malloc(sizeof(**filecon)); (*filecon)->path_str = NULL; (*filecon)->type = 0; (*filecon)->context_str = NULL; (*filecon)->context = NULL; } void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon) { *ibpkeycon = cil_malloc(sizeof(**ibpkeycon)); (*ibpkeycon)->subnet_prefix_str = NULL; (*ibpkeycon)->pkey_low = 0; (*ibpkeycon)->pkey_high = 0; (*ibpkeycon)->context_str = NULL; (*ibpkeycon)->context = NULL; } void cil_portcon_init(struct cil_portcon **portcon) { *portcon = cil_malloc(sizeof(**portcon)); (*portcon)->proto = 0; (*portcon)->port_low = 0; (*portcon)->port_high = 0; (*portcon)->context_str = NULL; (*portcon)->context = NULL; } void cil_nodecon_init(struct cil_nodecon **nodecon) { *nodecon = cil_malloc(sizeof(**nodecon)); (*nodecon)->addr_str = NULL; (*nodecon)->addr = NULL; (*nodecon)->mask_str = NULL; (*nodecon)->mask = NULL; (*nodecon)->context_str = NULL; (*nodecon)->context = NULL; } void cil_genfscon_init(struct cil_genfscon **genfscon) { *genfscon = cil_malloc(sizeof(**genfscon)); (*genfscon)->fs_str = NULL; (*genfscon)->path_str = NULL; (*genfscon)->context_str = NULL; (*genfscon)->context = NULL; } void cil_pirqcon_init(struct cil_pirqcon **pirqcon) { *pirqcon = cil_malloc(sizeof(**pirqcon)); (*pirqcon)->pirq = 0; (*pirqcon)->context_str = NULL; (*pirqcon)->context = NULL; } void cil_iomemcon_init(struct cil_iomemcon **iomemcon) { *iomemcon = cil_malloc(sizeof(**iomemcon)); (*iomemcon)->iomem_low = 0; (*iomemcon)->iomem_high = 0; (*iomemcon)->context_str = NULL; (*iomemcon)->context = NULL; } void cil_ioportcon_init(struct cil_ioportcon **ioportcon) { *ioportcon = cil_malloc(sizeof(**ioportcon)); (*ioportcon)->context_str = NULL; (*ioportcon)->context = NULL; } void cil_pcidevicecon_init(struct cil_pcidevicecon **pcidevicecon) { *pcidevicecon = cil_malloc(sizeof(**pcidevicecon)); (*pcidevicecon)->dev = 0; (*pcidevicecon)->context_str = NULL; (*pcidevicecon)->context = NULL; } void cil_devicetreecon_init(struct cil_devicetreecon **dtcon) { *dtcon = cil_malloc(sizeof(**dtcon)); (*dtcon)->path = NULL; (*dtcon)->context_str = NULL; (*dtcon)->context = NULL; } void cil_fsuse_init(struct cil_fsuse **fsuse) { *fsuse = cil_malloc(sizeof(**fsuse)); (*fsuse)->type = 0; (*fsuse)->fs_str = NULL; (*fsuse)->context_str = NULL; (*fsuse)->context = NULL; } void cil_constrain_init(struct cil_constrain **constrain) { *constrain = cil_malloc(sizeof(**constrain)); (*constrain)->classperms = NULL; (*constrain)->str_expr = NULL; (*constrain)->datum_expr = NULL; } void cil_validatetrans_init(struct cil_validatetrans **validtrans) { *validtrans = cil_malloc(sizeof(**validtrans)); (*validtrans)->class_str = NULL; (*validtrans)->class = NULL; (*validtrans)->str_expr = NULL; (*validtrans)->datum_expr = NULL; } void cil_ipaddr_init(struct cil_ipaddr **ipaddr) { *ipaddr = cil_malloc(sizeof(**ipaddr)); cil_symtab_datum_init(&(*ipaddr)->datum); memset(&(*ipaddr)->ip, 0, sizeof((*ipaddr)->ip)); } void cil_perm_init(struct cil_perm **perm) { *perm = cil_malloc(sizeof(**perm)); cil_symtab_datum_init(&(*perm)->datum); (*perm)->value = 0; (*perm)->classperms = NULL; } void cil_classpermission_init(struct cil_classpermission **cp) { *cp = cil_malloc(sizeof(**cp)); cil_symtab_datum_init(&(*cp)->datum); (*cp)->classperms = NULL; } void cil_classpermissionset_init(struct cil_classpermissionset **cps) { *cps = cil_malloc(sizeof(**cps)); (*cps)->set_str = NULL; (*cps)->classperms = NULL; } void cil_classperms_set_init(struct cil_classperms_set **cp_set) { *cp_set = cil_malloc(sizeof(**cp_set)); (*cp_set)->set_str = NULL; (*cp_set)->set = NULL; } void cil_classperms_init(struct cil_classperms **cp) { *cp = cil_malloc(sizeof(**cp)); (*cp)->class_str = NULL; (*cp)->class = NULL; (*cp)->perm_strs = NULL; (*cp)->perms = NULL; } void cil_classmapping_init(struct cil_classmapping **mapping) { *mapping = cil_malloc(sizeof(**mapping)); (*mapping)->map_class_str = NULL; (*mapping)->map_perm_str = NULL; (*mapping)->classperms = NULL; } void cil_user_init(struct cil_user **user) { *user = cil_malloc(sizeof(**user)); cil_symtab_datum_init(&(*user)->datum); (*user)->bounds = NULL; (*user)->roles = NULL; (*user)->dftlevel = NULL; (*user)->range = NULL; (*user)->value = 0; } void cil_userattribute_init(struct cil_userattribute **attr) { *attr = cil_malloc(sizeof(**attr)); cil_symtab_datum_init(&(*attr)->datum); (*attr)->expr_list = NULL; (*attr)->users = NULL; } void cil_userattributeset_init(struct cil_userattributeset **attrset) { *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_userlevel_init(struct cil_userlevel **usrlvl) { *usrlvl = cil_malloc(sizeof(**usrlvl)); (*usrlvl)->user_str = NULL; (*usrlvl)->level_str = NULL; (*usrlvl)->level = NULL; } void cil_userrange_init(struct cil_userrange **userrange) { *userrange = cil_malloc(sizeof(**userrange)); (*userrange)->user_str = NULL; (*userrange)->range_str = NULL; (*userrange)->range = NULL; } void cil_role_init(struct cil_role **role) { *role = cil_malloc(sizeof(**role)); cil_symtab_datum_init(&(*role)->datum); (*role)->bounds = NULL; (*role)->types = NULL; (*role)->value = 0; } void cil_type_init(struct cil_type **type) { *type = cil_malloc(sizeof(**type)); cil_symtab_datum_init(&(*type)->datum); (*type)->bounds = NULL; (*type)->value = 0; } void cil_cat_init(struct cil_cat **cat) { *cat = cil_malloc(sizeof(**cat)); cil_symtab_datum_init(&(*cat)->datum); (*cat)->ordered = CIL_FALSE; (*cat)->value = 0; } void cil_catorder_init(struct cil_catorder **catorder) { *catorder = cil_malloc(sizeof(**catorder)); (*catorder)->cat_list_str = NULL; } void cil_sensorder_init(struct cil_sensorder **sensorder) { *sensorder = cil_malloc(sizeof(**sensorder)); (*sensorder)->sens_list_str = NULL; } void cil_args_init(struct cil_args **args) { *args = cil_malloc(sizeof(**args)); (*args)->arg_str = NULL; (*args)->arg = NULL; (*args)->param_str = NULL; (*args)->flavor = CIL_NONE; } void cil_call_init(struct cil_call **call) { *call = cil_malloc(sizeof(**call)); (*call)->macro_str = NULL; (*call)->macro = NULL; (*call)->args_tree = NULL; (*call)->args = NULL; (*call)->copied = 0; } void cil_optional_init(struct cil_optional **optional) { *optional = cil_malloc(sizeof(**optional)); (*optional)->enabled = CIL_TRUE; cil_symtab_datum_init(&(*optional)->datum); } void cil_param_init(struct cil_param **param) { *param = cil_malloc(sizeof(**param)); (*param)->str = NULL; (*param)->flavor = CIL_NONE; } void cil_macro_init(struct cil_macro **macro) { *macro = cil_malloc(sizeof(**macro)); cil_symtab_datum_init(&(*macro)->datum); cil_symtab_array_init((*macro)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_MACRO]); (*macro)->params = NULL; } void cil_policycap_init(struct cil_policycap **policycap) { *policycap = cil_malloc(sizeof(**policycap)); cil_symtab_datum_init(&(*policycap)->datum); } void cil_bounds_init(struct cil_bounds **bounds) { *bounds = cil_malloc(sizeof(**bounds)); (*bounds)->parent_str = NULL; (*bounds)->child_str = NULL; } void cil_default_init(struct cil_default **def) { *def = cil_malloc(sizeof(**def)); (*def)->flavor = CIL_NONE; (*def)->class_strs = NULL; (*def)->class_datums = NULL; } void cil_defaultrange_init(struct cil_defaultrange **def) { *def = cil_malloc(sizeof(**def)); (*def)->class_strs = NULL; (*def)->class_datums = NULL; } void cil_handleunknown_init(struct cil_handleunknown **unk) { *unk = cil_malloc(sizeof(**unk)); } void cil_mls_init(struct cil_mls **mls) { *mls = cil_malloc(sizeof(**mls)); (*mls)->value = 0; } void cil_src_info_init(struct cil_src_info **info) { *info = cil_malloc(sizeof(**info)); (*info)->is_cil = 0; (*info)->path = NULL; } libsepol/cil/src/cil_binary.c0100644 0000000 0000000 00000405433 13756670064 015262 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_binary.h" #include "cil_symtab.h" #include "cil_find.h" #include "cil_build_ast.h" /* There are 44000 filename_trans in current fedora policy. 1.33 times this is the recommended * size of a hashtable. The next power of 2 of this is 2 ** 16. */ #define FILENAME_TRANS_TABLE_SIZE (1 << 16) #define RANGE_TRANS_TABLE_SIZE (1 << 13) #define ROLE_TRANS_TABLE_SIZE (1 << 10) #define AVRULEX_TABLE_SIZE (1 << 10) #define PERMS_PER_CLASS 32 struct cil_args_binary { const struct cil_db *db; policydb_t *pdb; struct cil_list *neverallows; int pass; hashtab_t filename_trans_table; hashtab_t range_trans_table; hashtab_t role_trans_table; hashtab_t avrulex_ioctl_table; void **type_value_to_cil; }; struct cil_args_booleanif { const struct cil_db *db; policydb_t *pdb; cond_node_t *cond_node; enum cil_flavor cond_flavor; hashtab_t filename_trans_table; }; static int __cil_get_sepol_user_datum(policydb_t *pdb, struct cil_symtab_datum *datum, user_datum_t **sepol_user) { *sepol_user = hashtab_search(pdb->p_users.table, datum->fqn); if (*sepol_user == NULL) { cil_log(CIL_INFO, "Failed to find user %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_role_datum(policydb_t *pdb, struct cil_symtab_datum *datum, role_datum_t **sepol_role) { *sepol_role = hashtab_search(pdb->p_roles.table, datum->fqn); if (*sepol_role == NULL) { cil_log(CIL_INFO, "Failed to find role %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_type_datum(policydb_t *pdb, struct cil_symtab_datum *datum, type_datum_t **sepol_type) { *sepol_type = hashtab_search(pdb->p_types.table, datum->fqn); if (*sepol_type == NULL) { cil_log(CIL_INFO, "Failed to find type %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_class_datum(policydb_t *pdb, struct cil_symtab_datum *datum, class_datum_t **sepol_class) { *sepol_class = hashtab_search(pdb->p_classes.table, datum->fqn); if (*sepol_class == NULL) { cil_log(CIL_INFO, "Failed to find class %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_cat_datum(policydb_t *pdb, struct cil_symtab_datum *datum, cat_datum_t **sepol_cat) { *sepol_cat = hashtab_search(pdb->p_cats.table, datum->fqn); if (*sepol_cat == NULL) { cil_log(CIL_INFO, "Failed to find category %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum *datum, level_datum_t **sepol_level) { *sepol_level = hashtab_search(pdb->p_levels.table, datum->fqn); if (*sepol_level == NULL) { cil_log(CIL_INFO, "Failed to find level %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_expand_user(struct cil_symtab_datum *datum, ebitmap_t *new) { struct cil_tree_node *node = datum->nodes->head->data; struct cil_user *user = NULL; struct cil_userattribute *attr = NULL; if (node->flavor == CIL_USERATTRIBUTE) { attr = (struct cil_userattribute *)datum; if (ebitmap_cpy(new, attr->users)) { cil_log(CIL_ERR, "Failed to copy user bits\n"); goto exit; } } else { user = (struct cil_user *)datum; ebitmap_init(new); if (ebitmap_set_bit(new, user->value, 1)) { cil_log(CIL_ERR, "Failed to set user bit\n"); ebitmap_destroy(new); goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new) { struct cil_tree_node *node = datum->nodes->head->data; if (node->flavor == CIL_ROLEATTRIBUTE) { struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; if (ebitmap_cpy(new, attr->roles)) { cil_log(CIL_ERR, "Failed to copy role bits\n"); goto exit; } } else { struct cil_role *role = (struct cil_role *)datum; ebitmap_init(new); if (ebitmap_set_bit(new, role->value, 1)) { cil_log(CIL_ERR, "Failed to set role bit\n"); ebitmap_destroy(new); goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_expand_type(struct cil_symtab_datum *datum, ebitmap_t *new) { struct cil_tree_node *node = datum->nodes->head->data; if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; if (ebitmap_cpy(new, attr->types)) { cil_log(CIL_ERR, "Failed to copy type bits\n"); goto exit; } } else { struct cil_type *type = (struct cil_type *)datum; ebitmap_init(new); if (ebitmap_set_bit(new, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(new); goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } static ocontext_t *cil_add_ocontext(ocontext_t **head, ocontext_t **tail) { ocontext_t *new = cil_malloc(sizeof(ocontext_t)); memset(new, 0, sizeof(ocontext_t)); if (*tail) { (*tail)->next = new; } else { *head = new; } *tail = new; return new; } int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common_datum_t **common_out) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_tree_node *node = cil_common->datum.nodes->head->data; struct cil_tree_node *cil_perm = node->cl_head; common_datum_t *sepol_common = cil_malloc(sizeof(*sepol_common)); memset(sepol_common, 0, sizeof(common_datum_t)); key = cil_strdup(cil_common->datum.fqn); rc = symtab_insert(pdb, SYM_COMMONS, key, sepol_common, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_common); goto exit; } sepol_common->s.value = value; rc = symtab_init(&sepol_common->permissions, PERM_SYMTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } while (cil_perm != NULL) { struct cil_perm *curr = cil_perm->data; perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); key = cil_strdup(curr->datum.fqn); rc = hashtab_insert(sepol_common->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); goto exit; } sepol_perm->s.value = sepol_common->permissions.nprim + 1; sepol_common->permissions.nprim++; cil_perm = cil_perm->next; } *common_out = sepol_common; return SEPOL_OK; exit: free(key); return rc; } int cil_classorder_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; struct cil_list_item *curr_class; cil_list_for_each(curr_class, db->classorder) { struct cil_class *cil_class = curr_class->data; uint32_t value = 0; char *key = NULL; int class_index; struct cil_tree_node *curr; common_datum_t *sepol_common = NULL; class_datum_t *sepol_class = cil_malloc(sizeof(*sepol_class)); memset(sepol_class, 0, sizeof(class_datum_t)); key = cil_strdup(cil_class->datum.fqn); rc = symtab_insert(pdb, SYM_CLASSES, key, sepol_class, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_class); free(key); goto exit; } sepol_class->s.value = value; class_index = value; class_value_to_cil[class_index] = cil_class; rc = symtab_init(&sepol_class->permissions, PERM_SYMTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } if (cil_class->common != NULL) { int i; struct cil_class *cil_common = cil_class->common; key = cil_class->common->datum.fqn; sepol_common = hashtab_search(pdb->p_commons.table, key); if (sepol_common == NULL) { rc = cil_common_to_policydb(pdb, cil_common, &sepol_common); if (rc != SEPOL_OK) { goto exit; } } sepol_class->comdatum = sepol_common; sepol_class->comkey = cil_strdup(key); sepol_class->permissions.nprim += sepol_common->permissions.nprim; for (curr = NODE(cil_class->common)->cl_head, i = 1; curr; curr = curr->next, i++) { struct cil_perm *cil_perm = curr->data; perm_value_to_cil[class_index][i] = cil_perm; } } for (curr = NODE(cil_class)->cl_head; curr; curr = curr->next) { struct cil_perm *cil_perm = curr->data; perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); key = cil_strdup(cil_perm->datum.fqn); rc = hashtab_insert(sepol_class->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); free(key); goto exit; } sepol_perm->s.value = sepol_class->permissions.nprim + 1; sepol_class->permissions.nprim++; perm_value_to_cil[class_index][sepol_perm->s.value] = cil_perm; } } return SEPOL_OK; exit: return rc; } int cil_role_to_policydb(policydb_t *pdb, struct cil_role *cil_role) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; role_datum_t *sepol_role = cil_malloc(sizeof(*sepol_role)); role_datum_init(sepol_role); if (cil_role->datum.fqn == CIL_KEY_OBJECT_R) { /* special case * object_r defaults to 1 in libsepol symtab */ rc = SEPOL_OK; goto exit; } key = cil_strdup(cil_role->datum.fqn); rc = symtab_insert(pdb, SYM_ROLES, (hashtab_key_t)key, sepol_role, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_set_bit(&sepol_role->dominates, value - 1, 1)) { cil_log(CIL_INFO, "Failed to set dominates bit for role\n"); rc = SEPOL_ERR; goto exit; } sepol_role->s.value = value; return SEPOL_OK; exit: free(key); role_datum_destroy(sepol_role); free(sepol_role); return rc; } int cil_role_bounds_to_policydb(policydb_t *pdb, struct cil_role *cil_role) { int rc = SEPOL_ERR; role_datum_t *sepol_role = NULL; role_datum_t *sepol_parent = NULL; if (cil_role->bounds) { rc = __cil_get_sepol_role_datum(pdb, DATUM(cil_role), &sepol_role); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_role_datum(pdb, DATUM(cil_role->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_role->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert role bounds for role %s\n", cil_role->datum.fqn); return SEPOL_ERR; } int cil_roletype_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_role *role) { int rc = SEPOL_ERR; if (role->types) { role_datum_t *sepol_role = NULL; type_datum_t *sepol_type = NULL; ebitmap_node_t *tnode; unsigned int i; rc = __cil_get_sepol_role_datum(pdb, DATUM(role), &sepol_role); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(role->types, tnode, i) { if (!ebitmap_get_bit(role->types, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_type); if (rc != SEPOL_OK) goto exit; if (ebitmap_set_bit(&sepol_role->types.types, sepol_type->s.value - 1, 1)) { cil_log(CIL_INFO, "Failed to set type bit for role\n"); rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type, void *type_value_to_cil[]) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; type_datum_t *sepol_type = cil_malloc(sizeof(*sepol_type)); type_datum_init(sepol_type); sepol_type->flavor = TYPE_TYPE; key = cil_strdup(cil_type->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_type, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_type->s.value = value; sepol_type->primary = 1; type_value_to_cil[value] = cil_type; return SEPOL_OK; exit: free(key); type_datum_destroy(sepol_type); free(sepol_type); return rc; } int cil_type_bounds_to_policydb(policydb_t *pdb, struct cil_type *cil_type) { int rc = SEPOL_ERR; type_datum_t *sepol_type = NULL; type_datum_t *sepol_parent = NULL; if (cil_type->bounds) { rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_type), &sepol_type); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_type->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_type->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert type bounds for type %s\n", cil_type->datum.fqn); return SEPOL_ERR; } int cil_typealias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; type_datum_t *sepol_type = NULL; type_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_alias)); type_datum_init(sepol_alias); rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_alias->actual), &sepol_type); if (rc != SEPOL_OK) goto exit; sepol_alias->flavor = TYPE_TYPE; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } sepol_alias->s.value = sepol_type->s.value; sepol_alias->primary = 0; return SEPOL_OK; exit: free(key); type_datum_destroy(sepol_alias); free(sepol_alias); return rc; } int cil_typepermissive_to_policydb(policydb_t *pdb, struct cil_typepermissive *cil_typeperm) { int rc = SEPOL_ERR; type_datum_t *sepol_type = NULL; rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_typeperm->type), &sepol_type); if (rc != SEPOL_OK) goto exit; if (ebitmap_set_bit(&pdb->permissive_map, sepol_type->s.value, 1)) { goto exit; } return SEPOL_OK; exit: type_datum_destroy(sepol_type); free(sepol_type); return rc; } int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr, void *type_value_to_cil[]) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; type_datum_t *sepol_attr = NULL; if (!cil_attr->keep) { return SEPOL_OK; } sepol_attr = cil_malloc(sizeof(*sepol_attr)); type_datum_init(sepol_attr); sepol_attr->flavor = TYPE_ATTRIB; key = cil_strdup(cil_attr->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_attr, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_attr->s.value = value; sepol_attr->primary = 1; type_value_to_cil[value] = cil_attr; return SEPOL_OK; exit: type_datum_destroy(sepol_attr); free(sepol_attr); return rc; } int __cil_typeattr_bitmap_init(policydb_t *pdb) { int rc = SEPOL_ERR; pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); uint32_t i = 0; for (i = 0; i < pdb->p_types.nprim; i++) { ebitmap_init(&pdb->type_attr_map[i]); ebitmap_init(&pdb->attr_type_map[i]); if (ebitmap_set_bit(&pdb->type_attr_map[i], i, 1)) { rc = SEPOL_ERR; goto exit; } if (pdb->type_val_to_struct[i] && pdb->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&pdb->attr_type_map[i], i, 1)) { rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *db, struct cil_typeattribute *cil_attr) { int rc = SEPOL_ERR; uint32_t value = 0; type_datum_t *sepol_type = NULL; ebitmap_node_t *tnode; unsigned int i; if (!cil_attr->keep) { return SEPOL_OK; } if (pdb->type_attr_map == NULL) { rc = __cil_typeattr_bitmap_init(pdb); if (rc != SEPOL_OK) { goto exit; } } rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_attr), &sepol_type); if (rc != SEPOL_OK) goto exit; value = sepol_type->s.value; ebitmap_for_each_bit(cil_attr->types, tnode, i) { if (!ebitmap_get_bit(cil_attr->types, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_type); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(&pdb->type_attr_map[sepol_type->s.value - 1], value - 1, 1); ebitmap_set_bit(&pdb->attr_type_map[value - 1], sepol_type->s.value - 1, 1); } rc = SEPOL_OK; exit: return rc; } int cil_policycap_to_policydb(policydb_t *pdb, struct cil_policycap *cil_polcap) { int rc = SEPOL_ERR; int capnum; capnum = sepol_polcap_getnum(cil_polcap->datum.fqn); if (capnum == -1) { goto exit; } if (ebitmap_set_bit(&pdb->policycaps, capnum, 1)) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; user_datum_t *sepol_user = cil_malloc(sizeof(*sepol_user)); user_datum_init(sepol_user); key = cil_strdup(cil_user->datum.fqn); rc = symtab_insert(pdb, SYM_USERS, key, sepol_user, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_user->s.value = value; return SEPOL_OK; exit: free(key); user_datum_destroy(sepol_user); free(sepol_user); return rc; } int cil_user_bounds_to_policydb(policydb_t *pdb, struct cil_user *cil_user) { int rc = SEPOL_ERR; user_datum_t *sepol_user = NULL; user_datum_t *sepol_parent = NULL; if (cil_user->bounds) { rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_user), &sepol_user); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_user->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_user->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert user bounds for user %s\n", cil_user->datum.fqn); return SEPOL_ERR; } int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user) { int rc = SEPOL_ERR; user_datum_t *sepol_user = NULL; role_datum_t *sepol_role = NULL; ebitmap_node_t *rnode = NULL; unsigned int i; if (user->roles) { rc = __cil_get_sepol_user_datum(pdb, DATUM(user), &sepol_user); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(user->roles, rnode, i) { if (!ebitmap_get_bit(user->roles, i)) { continue; } rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role); if (rc != SEPOL_OK) { goto exit; } if (sepol_role->s.value == 1) { // role is object_r, ignore it since it is implicitly associated // with all users continue; } if (ebitmap_set_bit(&sepol_user->roles.roles, sepol_role->s.value - 1, 1)) { cil_log(CIL_INFO, "Failed to set role bit for user\n"); rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: return rc; } int cil_bool_to_policydb(policydb_t *pdb, struct cil_bool *cil_bool) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; cond_bool_datum_t *sepol_bool = cil_malloc(sizeof(*sepol_bool)); memset(sepol_bool, 0, sizeof(cond_bool_datum_t)); key = cil_strdup(cil_bool->datum.fqn); rc = symtab_insert(pdb, SYM_BOOLS, key, sepol_bool, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_bool->s.value = value; sepol_bool->state = cil_bool->value; return SEPOL_OK; exit: free(key); free(sepol_bool); return rc; } int cil_catorder_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_list_item *curr_cat; struct cil_cat *cil_cat = NULL; cat_datum_t *sepol_cat = NULL; cil_list_for_each(curr_cat, db->catorder) { cil_cat = curr_cat->data; sepol_cat = cil_malloc(sizeof(*sepol_cat)); cat_datum_init(sepol_cat); key = cil_strdup(cil_cat->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_cat, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_cat->s.value = value; } return SEPOL_OK; exit: free(key); cat_datum_destroy(sepol_cat); free(sepol_cat); return rc; } int cil_catalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; cat_datum_t *sepol_cat; cat_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_cat)); cat_datum_init(sepol_alias); rc = __cil_get_sepol_cat_datum(pdb, DATUM(cil_alias->actual), &sepol_cat); if (rc != SEPOL_OK) goto exit; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } sepol_alias->s.value = sepol_cat->s.value; sepol_alias->isalias = 1; return SEPOL_OK; exit: free(key); cat_datum_destroy(sepol_alias); free(sepol_alias); return rc; } int cil_sensitivityorder_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_list_item *curr; struct cil_sens *cil_sens = NULL; level_datum_t *sepol_level = NULL; mls_level_t *mls_level = NULL; cil_list_for_each(curr, db->sensitivityorder) { cil_sens = curr->data; sepol_level = cil_malloc(sizeof(*sepol_level)); mls_level = cil_malloc(sizeof(*mls_level)); level_datum_init(sepol_level); mls_level_init(mls_level); key = cil_strdup(cil_sens->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_level, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } mls_level->sens = value; sepol_level->level = mls_level; } return SEPOL_OK; exit: level_datum_destroy(sepol_level); mls_level_destroy(mls_level); free(sepol_level); free(mls_level); free(key); return rc; } int cil_sensalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; mls_level_t *mls_level = NULL; level_datum_t *sepol_level = NULL; level_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_alias)); level_datum_init(sepol_alias); rc = __cil_get_sepol_level_datum(pdb, DATUM(cil_alias->actual), &sepol_level); if (rc != SEPOL_OK) goto exit; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } mls_level = cil_malloc(sizeof(*mls_level)); mls_level_init(mls_level); rc = mls_level_cpy(mls_level, sepol_level->level); if (rc != SEPOL_OK) { goto exit; } sepol_alias->level = mls_level; sepol_alias->defined = 1; sepol_alias->isalias = 1; return SEPOL_OK; exit: level_datum_destroy(sepol_alias); free(sepol_alias); free(key); return rc; } int __cil_cond_insert_rule(avtab_t *avtab, avtab_key_t *avtab_key, avtab_datum_t *avtab_datum, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_OK; avtab_ptr_t avtab_ptr = NULL; cond_av_list_t *cond_list = NULL; avtab_ptr = avtab_insert_nonunique(avtab, avtab_key, avtab_datum); if (!avtab_ptr) { rc = SEPOL_ERR; goto exit; } // parse_context needs to be non-NULL for conditional rules to be // written to the binary. it is normally used for finding duplicates, // but cil checks that earlier, so we don't use it. it just needs to be // set avtab_ptr->parse_context = (void*)1; cond_list = cil_malloc(sizeof(cond_av_list_t)); memset(cond_list, 0, sizeof(cond_av_list_t)); cond_list->node = avtab_ptr; if (cond_flavor == CIL_CONDTRUE) { cond_list->next = cond_node->true_list; cond_node->true_list = cond_list; } else { cond_list->next = cond_node->false_list; cond_node->false_list = cond_list; } exit: return rc; } avtab_datum_t *cil_cond_av_list_search(avtab_key_t *key, cond_av_list_t *cond_list) { cond_av_list_t *cur_av; for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { if (cur_av->node->key.source_type == key->source_type && cur_av->node->key.target_type == key->target_type && cur_av->node->key.target_class == key->target_class && (cur_av->node->key.specified & key->specified)) return &cur_av->node->datum; } return NULL; } int __cil_insert_type_rule(policydb_t *pdb, uint32_t kind, uint32_t src, uint32_t tgt, uint32_t obj, uint32_t res, struct cil_type_rule *cil_rule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_OK; avtab_key_t avtab_key; avtab_datum_t avtab_datum; avtab_ptr_t existing; avtab_key.source_type = src; avtab_key.target_type = tgt; avtab_key.target_class = obj; switch (kind) { case CIL_TYPE_TRANSITION: avtab_key.specified = AVTAB_TRANSITION; break; case CIL_TYPE_CHANGE: avtab_key.specified = AVTAB_CHANGE; break; case CIL_TYPE_MEMBER: avtab_key.specified = AVTAB_MEMBER; break; default: rc = SEPOL_ERR; goto exit; } avtab_datum.data = res; existing = avtab_search_node(&pdb->te_avtab, &avtab_key); if (existing) { /* Don't add duplicate type rule and warn if they conflict. * A warning should have been previously given if there is a * non-duplicate rule using the same key. */ if (existing->datum.data != res) { cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n", pdb->p_type_val_to_name[src - 1], pdb->p_type_val_to_name[tgt - 1], pdb->p_class_val_to_name[obj - 1], pdb->p_type_val_to_name[res - 1], pdb->p_type_val_to_name[existing->datum.data - 1]); cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n", cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str); rc = SEPOL_ERR; } goto exit; } if (!cond_node) { rc = avtab_insert(&pdb->te_avtab, &avtab_key, &avtab_datum); } else { existing = avtab_search_node(&pdb->te_cond_avtab, &avtab_key); if (existing) { cond_av_list_t *this_list; cond_av_list_t *other_list; avtab_datum_t *search_datum; if (cond_flavor == CIL_CONDTRUE) { this_list = cond_node->true_list; other_list = cond_node->false_list; } else { this_list = cond_node->false_list; other_list = cond_node->true_list; } search_datum = cil_cond_av_list_search(&avtab_key, other_list); if (search_datum == NULL) { if (existing->datum.data != res) { cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n", pdb->p_type_val_to_name[src - 1], pdb->p_type_val_to_name[tgt - 1], pdb->p_class_val_to_name[obj - 1], pdb->p_type_val_to_name[res - 1], pdb->p_type_val_to_name[existing->datum.data - 1]); cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n", cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str); rc = SEPOL_ERR; goto exit; } search_datum = cil_cond_av_list_search(&avtab_key, this_list); if (search_datum) { goto exit; } } } rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, &avtab_key, &avtab_datum, cond_node, cond_flavor); } exit: return rc; } int __cil_type_rule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_type_rule *cil_rule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; uint16_t kind = cil_rule->rule_kind; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list; type_datum_t *sepol_result = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; struct cil_list_item *c; rc = __cil_expand_type(cil_rule->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_type(cil_rule->tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(cil_rule->obj); rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_rule->result), &sepol_result); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&src_bitmap, node1, i) { if (!ebitmap_get_bit(&src_bitmap, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&tgt_bitmap, node2, j) { if (!ebitmap_get_bit(&tgt_bitmap, j)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; rc = __cil_insert_type_rule(pdb, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, sepol_result->s.value, cil_rule, cond_node, cond_flavor); if (rc != SEPOL_OK) goto exit; } } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_type_rule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_type_rule *cil_rule) { return __cil_type_rule_to_avtab(pdb, db, cil_rule, NULL, CIL_FALSE); } int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_nametypetransition *typetrans, cond_node_t *cond_node, enum cil_flavor cond_flavor, hashtab_t filename_trans_table) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list; type_datum_t *sepol_result = NULL; filename_trans_t *newkey = NULL; filename_trans_datum_t *newdatum = NULL, *otype = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; struct cil_list_item *c; char *name = DATUM(typetrans->name)->name; if (name == CIL_KEY_STAR) { struct cil_type_rule trans; trans.rule_kind = CIL_TYPE_TRANSITION; trans.src = typetrans->src; trans.tgt = typetrans->tgt; trans.obj = typetrans->obj; trans.result = typetrans->result; trans.src_str = typetrans->src_str; trans.tgt_str = typetrans->tgt_str; trans.obj_str = typetrans->obj_str; trans.result_str = typetrans->result_str; return __cil_type_rule_to_avtab(pdb, db, &trans, cond_node, cond_flavor); } rc = __cil_expand_type(typetrans->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_type(typetrans->tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(typetrans->obj); rc = __cil_get_sepol_type_datum(pdb, DATUM(typetrans->result), &sepol_result); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&src_bitmap, node1, i) { if (!ebitmap_get_bit(&src_bitmap, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&tgt_bitmap, node2, j) { if (!ebitmap_get_bit(&tgt_bitmap, j)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; cil_list_for_each(c, class_list) { int add = CIL_TRUE; rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; newkey = cil_calloc(1, sizeof(*newkey)); newdatum = cil_calloc(1, sizeof(*newdatum)); newkey->stype = sepol_src->s.value; newkey->ttype = sepol_tgt->s.value; newkey->tclass = sepol_obj->s.value; newkey->name = cil_strdup(name); newdatum->otype = sepol_result->s.value; rc = hashtab_insert(filename_trans_table, (hashtab_key_t)newkey, newdatum); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { add = CIL_FALSE; otype = hashtab_search(filename_trans_table, (hashtab_key_t)newkey); if (newdatum->otype != otype->otype) { cil_log(CIL_ERR, "Conflicting name type transition rules\n"); } else { rc = SEPOL_OK; } } else { cil_log(CIL_ERR, "Out of memory\n"); } } if (add == CIL_TRUE) { rc = hashtab_insert(pdb->filename_trans, (hashtab_key_t)newkey, newdatum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Out of memory\n"); goto exit; } } else { free(newkey->name); free(newkey); free(newdatum); if (rc != SEPOL_OK) { goto exit; } } } } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_typetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_nametypetransition *typetrans, hashtab_t filename_trans_table) { return __cil_typetransition_to_avtab(pdb, db, typetrans, NULL, CIL_FALSE, filename_trans_table); } int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *datum) { int rc; perm_datum_t *sepol_perm; common_datum_t *sepol_common; sepol_perm = hashtab_search(sepol_class->permissions.table, perm_str); if (sepol_perm == NULL) { sepol_common = sepol_class->comdatum; sepol_perm = hashtab_search(sepol_common->permissions.table, perm_str); if (sepol_perm == NULL) { cil_log(CIL_ERR, "Failed to find datum for perm %s\n", perm_str); rc = SEPOL_ERR; goto exit; } } *datum |= 1 << (sepol_perm->s.value - 1); return SEPOL_OK; exit: return rc; } int __cil_perms_to_datum(struct cil_list *perms, class_datum_t *sepol_class, uint32_t *datum) { int rc = SEPOL_ERR; char *key = NULL; struct cil_list_item *curr_perm; struct cil_perm *cil_perm; uint32_t data = 0; cil_list_for_each(curr_perm, perms) { cil_perm = curr_perm->data; key = cil_perm->datum.fqn; rc = __perm_str_to_datum(key, sepol_class, &data); if (rc != SEPOL_OK) { goto exit; } } *datum = data; return SEPOL_OK; exit: return rc; } int __cil_insert_avrule(policydb_t *pdb, uint32_t kind, uint32_t src, uint32_t tgt, uint32_t obj, uint32_t data, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_OK; avtab_key_t avtab_key; avtab_datum_t avtab_datum; avtab_datum_t *avtab_dup = NULL; avtab_key.source_type = src; avtab_key.target_type = tgt; avtab_key.target_class = obj; switch (kind) { case CIL_AVRULE_ALLOWED: avtab_key.specified = AVTAB_ALLOWED; break; case CIL_AVRULE_AUDITALLOW: avtab_key.specified = AVTAB_AUDITALLOW; break; case CIL_AVRULE_DONTAUDIT: avtab_key.specified = AVTAB_AUDITDENY; break; default: rc = SEPOL_ERR; goto exit; break; } if (!cond_node) { avtab_dup = avtab_search(&pdb->te_avtab, &avtab_key); if (!avtab_dup) { avtab_datum.data = data; rc = avtab_insert(&pdb->te_avtab, &avtab_key, &avtab_datum); } else { if (kind == CIL_AVRULE_DONTAUDIT) avtab_dup->data &= data; else avtab_dup->data |= data; } } else { avtab_datum.data = data; rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, &avtab_key, &avtab_datum, cond_node, cond_flavor); } exit: return rc; } int __cil_avrule_expand_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_classperms *cp, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_class = NULL; uint32_t data = 0; rc = __cil_get_sepol_class_datum(pdb, DATUM(cp->class), &sepol_class); if (rc != SEPOL_OK) goto exit; rc = __cil_perms_to_datum(cp->perms, sepol_class, &data); if (rc != SEPOL_OK) goto exit; if (data == 0) { /* No permissions, so don't insert rule. Maybe should return an error? */ return SEPOL_OK; } if (kind == CIL_AVRULE_DONTAUDIT) { data = ~data; } rc = __cil_get_sepol_type_datum(pdb, src, &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, tgt, &sepol_tgt); if (rc != SEPOL_OK) goto exit; rc = __cil_insert_avrule(pdb, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_class->s.value, data, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int __cil_avrule_expand(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __cil_avrule_expand_helper(pdb, kind, src, tgt, cp, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __cil_avrule_expand(pdb, kind, src, tgt, cmp->classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_avrule_expand(pdb, kind, src, tgt, cp->classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int __cil_should_expand_attribute( const struct cil_db *db, struct cil_symtab_datum *datum) { struct cil_tree_node *node; struct cil_typeattribute *attr; node = NODE(datum); if (node->flavor != CIL_TYPEATTRIBUTE) { return CIL_FALSE; } attr = (struct cil_typeattribute *)datum; return !attr->keep || (ebitmap_cardinality(attr->types) < db->attrs_expand_size); } int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; uint16_t kind = cil_avrule->rule_kind; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; struct cil_list *classperms = cil_avrule->perms.classperms; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (cil_avrule->rule_kind == CIL_AVRULE_DONTAUDIT && db->disable_dontaudit == CIL_TRUE) { // Do not add dontaudit rules to binary rc = SEPOL_OK; goto exit; } src = cil_avrule->src; tgt = cil_avrule->tgt; if (tgt->fqn == CIL_KEY_SELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); rc = __cil_avrule_expand(pdb, kind, src, src, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); if (!expand_src && !expand_tgt) { rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } else if (expand_src && expand_tgt) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); ebitmap_for_each_bit(&tgt_bitmap, tnode, t) { if (!ebitmap_get_bit(&tgt_bitmap, t)) continue; tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); goto exit; } } } ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); } else if (expand_src) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else { /* expand_tgt */ rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(&tgt_bitmap, tnode, t) { if (!ebitmap_get_bit(&tgt_bitmap, t)) continue; tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&tgt_bitmap); goto exit; } } ebitmap_destroy(&tgt_bitmap); } } return SEPOL_OK; exit: return rc; } int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule) { return __cil_avrule_to_avtab(pdb, db, cil_avrule, NULL, CIL_FALSE); } // Copied from checkpolicy/policy_define.c /* index of the u32 containing the permission */ #define XPERM_IDX(x) (x >> 5) /* set bits 0 through x-1 within the u32 */ #define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1) /* low value for this u32 */ #define XPERM_LOW(x) (x << 5) /* high value for this u32 */ #define XPERM_HIGH(x) (((x + 1) << 5) - 1) void __avrule_xperm_setrangebits(uint16_t low, uint16_t high, struct avtab_extended_perms *xperms) { unsigned int i; uint16_t h = high + 1; /* for each u32 that this low-high range touches, set driver permissions */ for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) { /* set all bits in u32 */ if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U; /* set low bits */ else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h); /* set high bits */ else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U - XPERM_SETBITS(low); /* set middle bits */ else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low); } } #define IOC_DRIV(x) (x >> 8) #define IOC_FUNC(x) (x & 0xff) int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil_list **xperms_list) { ebitmap_node_t *node; unsigned int i; uint16_t low = 0, high = 0; struct avtab_extended_perms *partial = NULL; struct avtab_extended_perms *complete = NULL; int start_new_range; cil_list_init(xperms_list, CIL_NONE); start_new_range = 1; ebitmap_for_each_bit(xperms, node, i) { if (!ebitmap_get_bit(xperms, i)) continue; if (start_new_range) { low = i; start_new_range = 0; } // continue if the current bit isn't the end of the driver function or the next bit is set if (IOC_FUNC(i) != 0xff && ebitmap_get_bit(xperms, i + 1)) { continue; } // if we got here, i is the end of this range (either becuase the func // is 0xff or the next bit isn't set). The next time around we are // going to need a start a new range high = i; start_new_range = 1; if (IOC_FUNC(low) == 0x00 && IOC_FUNC(high) == 0xff) { if (!complete) { complete = cil_calloc(1, sizeof(*complete)); complete->driver = 0x0; complete->specified = AVTAB_XPERMS_IOCTLDRIVER; } __avrule_xperm_setrangebits(IOC_DRIV(low), IOC_DRIV(low), complete); } else { if (partial && partial->driver != IOC_DRIV(low)) { cil_list_append(*xperms_list, CIL_NONE, partial); partial = NULL; } if (!partial) { partial = cil_calloc(1, sizeof(*partial)); partial->driver = IOC_DRIV(low); partial->specified = AVTAB_XPERMS_IOCTLFUNCTION; } __avrule_xperm_setrangebits(IOC_FUNC(low), IOC_FUNC(high), partial); } } if (partial) { cil_list_append(*xperms_list, CIL_NONE, partial); } if (complete) { cil_list_append(*xperms_list, CIL_NONE, complete); } return SEPOL_OK; } int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args) { int rc = SEPOL_OK; struct policydb *pdb; avtab_key_t *avtab_key; avtab_datum_t avtab_datum; struct cil_list *xperms_list = NULL; struct cil_list_item *item; class_datum_t *sepol_obj; uint32_t data = 0; avtab_key = (avtab_key_t *)k; pdb = args; sepol_obj = pdb->class_val_to_struct[avtab_key->target_class - 1]; // setting the data for an extended avtab isn't really neccessary because // it is ignored by the kernel. However, neverallow checking requires that // the data value be set, so set it for that to work. rc = __perm_str_to_datum(CIL_KEY_IOCTL, sepol_obj, &data); if (rc != SEPOL_OK) { goto exit; } avtab_datum.data = data; rc = __cil_permx_bitmap_to_sepol_xperms_list(datum, &xperms_list); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(item, xperms_list) { avtab_datum.xperms = item->data; rc = avtab_insert(&pdb->te_avtab, avtab_key, &avtab_datum); if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: if (xperms_list != NULL) { cil_list_for_each(item, xperms_list) { free(item->data); } cil_list_destroy(&xperms_list, CIL_FALSE); } // hashtab_t does not have a way to free keys or datum since it doesn't // know what they are. We won't need the keys/datum after this function, so // clean them up here. free(avtab_key); ebitmap_destroy(datum); free(datum); return rc; } int __cil_avrulex_ioctl_to_hashtable(hashtab_t h, uint16_t kind, uint32_t src, uint32_t tgt, uint32_t obj, ebitmap_t *xperms) { uint16_t specified; avtab_key_t *avtab_key; ebitmap_t *hashtab_xperms; int rc = SEPOL_ERR; switch (kind) { case CIL_AVRULE_ALLOWED: specified = AVTAB_XPERMS_ALLOWED; break; case CIL_AVRULE_AUDITALLOW: specified = AVTAB_XPERMS_AUDITALLOW; break; case CIL_AVRULE_DONTAUDIT: specified = AVTAB_XPERMS_DONTAUDIT; break; default: rc = SEPOL_ERR; goto exit; } avtab_key = cil_malloc(sizeof(*avtab_key)); avtab_key->source_type = src; avtab_key->target_type = tgt; avtab_key->target_class = obj; avtab_key->specified = specified; hashtab_xperms = (ebitmap_t *)hashtab_search(h, (hashtab_key_t)avtab_key); if (!hashtab_xperms) { hashtab_xperms = cil_malloc(sizeof(*hashtab_xperms)); rc = ebitmap_cpy(hashtab_xperms, xperms); if (rc != SEPOL_OK) { free(hashtab_xperms); free(avtab_key); goto exit; } rc = hashtab_insert(h, (hashtab_key_t)avtab_key, hashtab_xperms); if (rc != SEPOL_OK) { free(hashtab_xperms); free(avtab_key); goto exit; } } else { free(avtab_key); rc = ebitmap_union(hashtab_xperms, xperms); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_permissionx *permx, struct cil_args_binary *args) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list = NULL; struct cil_list_item *c; rc = __cil_get_sepol_type_datum(pdb, src, &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, tgt, &sepol_tgt); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(permx->obj); cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: rc = __cil_avrulex_ioctl_to_hashtable(args->avrulex_ioctl_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); if (rc != SEPOL_OK) goto exit; break; default: rc = SEPOL_ERR; goto exit; } } rc = SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrulex, struct cil_args_binary *args) { int rc = SEPOL_ERR; uint16_t kind; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (cil_avrulex->rule_kind == CIL_AVRULE_DONTAUDIT && db->disable_dontaudit == CIL_TRUE) { // Do not add dontaudit rules to binary rc = SEPOL_OK; goto exit; } kind = cil_avrulex->rule_kind; src = cil_avrulex->src; tgt = cil_avrulex->tgt; if (tgt->fqn == CIL_KEY_SELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { goto exit; } } ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); if (!expand_src && !expand_tgt) { rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { goto exit; } } else if (expand_src && expand_tgt) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); ebitmap_for_each_bit(&tgt_bitmap, tnode, t) { if (!ebitmap_get_bit(&tgt_bitmap, t)) continue; tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); goto exit; } } } ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); } else if (expand_src) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(&src_bitmap, snode, s) { if (!ebitmap_get_bit(&src_bitmap, s)) continue; src = DATUM(db->val_to_type[s]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else { /* expand_tgt */ rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_bit(&tgt_bitmap, tnode, t) { if (!ebitmap_get_bit(&tgt_bitmap, t)) continue; tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { ebitmap_destroy(&tgt_bitmap); goto exit; } } ebitmap_destroy(&tgt_bitmap); } } return SEPOL_OK; exit: return rc; } int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) { int rc; enum cil_flavor flavor; struct cil_args_booleanif *args = extra_args; const struct cil_db *db = args->db; policydb_t *pdb = args->pdb; cond_node_t *cond_node = args->cond_node; enum cil_flavor cond_flavor = args->cond_flavor; struct cil_type_rule *cil_type_rule; struct cil_avrule *cil_avrule; struct cil_nametypetransition *cil_typetrans; hashtab_t filename_trans_table = args->filename_trans_table; flavor = node->flavor; switch (flavor) { case CIL_NAMETYPETRANSITION: cil_typetrans = (struct cil_nametypetransition*)node->data; if (DATUM(cil_typetrans->name)->fqn != CIL_KEY_STAR) { cil_log(CIL_ERR, "typetransition with file name not allowed within a booleanif block.\n"); cil_tree_log(node, CIL_ERR,"Invalid typetransition statement"); goto exit; } rc = __cil_typetransition_to_avtab(pdb, db, cil_typetrans, cond_node, cond_flavor, filename_trans_table); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert type transition into avtab"); goto exit; } break; case CIL_TYPE_RULE: cil_type_rule = node->data; rc = __cil_type_rule_to_avtab(pdb, db, cil_type_rule, cond_node, cond_flavor); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert typerule into avtab"); goto exit; } break; case CIL_AVRULE: cil_avrule = node->data; rc = __cil_avrule_to_avtab(pdb, db, cil_avrule, cond_node, cond_flavor); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert avrule into avtab"); goto exit; } break; case CIL_CALL: case CIL_TUNABLEIF: break; default: cil_tree_log(node, CIL_ERR, "Invalid statement within booleanif"); goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor, char **out); static void __cil_expr_to_string_helper(struct cil_list_item *curr, enum cil_flavor flavor, char **out) { char *c; if (curr->flavor == CIL_DATUM) { *out = cil_strdup(DATUM(curr->data)->fqn); } else if (curr->flavor == CIL_LIST) { __cil_expr_to_string(curr->data, flavor, &c); cil_asprintf(out, "(%s)", c); free(c); } else if (flavor == CIL_PERMISSIONX) { // permissionx expressions aren't resolved into anything, so curr->flavor // is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those *out = cil_strdup(curr->data); } } static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor, char **out) { struct cil_list_item *curr; char *s1 = NULL; char *s2 = NULL; enum cil_flavor op; if (expr == NULL || expr->head == NULL) { *out = cil_strdup(""); return; } curr = expr->head; if (curr->flavor == CIL_OP) { op = (enum cil_flavor)curr->data; if (op == CIL_ALL) { *out = cil_strdup(CIL_KEY_ALL); } else if (op == CIL_RANGE) { __cil_expr_to_string_helper(curr->next, flavor, &s1); __cil_expr_to_string_helper(curr->next->next, flavor, &s2); cil_asprintf(out, "%s %s %s", CIL_KEY_RANGE, s1, s2); free(s1); free(s2); } else { __cil_expr_to_string_helper(curr->next, flavor, &s1); if (op == CIL_NOT) { cil_asprintf(out, "%s %s", CIL_KEY_NOT, s1); free(s1); } else { const char *opstr = ""; __cil_expr_to_string_helper(curr->next->next, flavor, &s2); if (op == CIL_OR) { opstr = CIL_KEY_OR; } else if (op == CIL_AND) { opstr = CIL_KEY_AND; } else if (op == CIL_XOR) { opstr = CIL_KEY_XOR; } cil_asprintf(out, "%s %s %s", opstr, s1, s2); free(s1); free(s2); } } } else { char *c1 = NULL; char *c2 = NULL; __cil_expr_to_string_helper(curr, flavor, &c1); for (curr = curr->next; curr; curr = curr->next) { s1 = NULL; __cil_expr_to_string_helper(curr, flavor, &s1); cil_asprintf(&c2, "%s %s", c1, s1); free(c1); free(s1); c1 = c2; } *out = c1; } } static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list *cil_expr, cond_expr_t **head, cond_expr_t **tail); static int __cil_cond_item_to_sepol_expr(policydb_t *pdb, struct cil_list_item *item, cond_expr_t **head, cond_expr_t **tail) { if (item == NULL) { goto exit; } else if (item->flavor == CIL_DATUM) { char *key = DATUM(item->data)->fqn; cond_bool_datum_t *sepol_bool = hashtab_search(pdb->p_bools.table, key); if (sepol_bool == NULL) { cil_log(CIL_INFO, "Failed to find boolean\n"); goto exit; } *head = cil_malloc(sizeof(cond_expr_t)); (*head)->next = NULL; (*head)->expr_type = COND_BOOL; (*head)->bool = sepol_bool->s.value; *tail = *head; } else if (item->flavor == CIL_LIST) { struct cil_list *l = item->data; int rc = __cil_cond_expr_to_sepol_expr_helper(pdb, l, head, tail); if (rc != SEPOL_OK) { goto exit; } } else { goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list *cil_expr, cond_expr_t **head, cond_expr_t **tail) { int rc = SEPOL_ERR; struct cil_list_item *item = cil_expr->head; enum cil_flavor flavor = cil_expr->flavor; cond_expr_t *op, *h1, *h2, *t1, *t2; if (flavor != CIL_BOOL) { cil_log(CIL_INFO, "Expected boolean expression\n"); goto exit; } if (item == NULL) { goto exit; } else if (item->flavor == CIL_OP) { enum cil_flavor cil_op = (enum cil_flavor)item->data; op = cil_malloc(sizeof(*op)); op->bool = 0; op->next = NULL; switch (cil_op) { case CIL_NOT: op->expr_type = COND_NOT; break; case CIL_OR: op->expr_type = COND_OR; break; case CIL_AND: op->expr_type = COND_AND; break; case CIL_XOR: op->expr_type = COND_XOR; break; case CIL_EQ: op->expr_type = COND_EQ; break; case CIL_NEQ: op->expr_type = COND_NEQ; break; default: free(op); goto exit; } rc = __cil_cond_item_to_sepol_expr(pdb, item->next, &h1, &t1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get first operand of conditional expression\n"); free(op); goto exit; } if (cil_op == CIL_NOT) { *head = h1; t1->next = op; *tail = op; } else { rc = __cil_cond_item_to_sepol_expr(pdb, item->next->next, &h2, &t2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get second operand of conditional expression\n"); free(op); cond_expr_destroy(h1); goto exit; } *head = h1; t1->next = h2; t2->next = op; *tail = op; } } else { rc = __cil_cond_item_to_sepol_expr(pdb, item, &h1, &t1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get initial item in conditional list\n"); goto exit; } *head = h1; for (item = item->next; item; item = item->next) { rc = __cil_cond_item_to_sepol_expr(pdb, item, &h2, &t2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get item in conditional list\n"); cond_expr_destroy(*head); goto exit; } op = cil_malloc(sizeof(*op)); op->bool = 0; op->next = NULL; op->expr_type = COND_OR; t1->next = h2; t2->next = op; t1 = op; } *tail = t1; } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_expr, cond_expr_t **sepol_expr) { int rc; cond_expr_t *head, *tail; rc = __cil_cond_expr_to_sepol_expr_helper(pdb, cil_expr, &head, &tail); if (rc != SEPOL_OK) { return SEPOL_ERR; } *sepol_expr = head; return SEPOL_OK; } int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node, hashtab_t filename_trans_table) { int rc = SEPOL_ERR; struct cil_args_booleanif bool_args; struct cil_booleanif *cil_boolif = (struct cil_booleanif*)node->data; struct cil_tree_node *cb_node = node->cl_head; struct cil_tree_node *true_node = NULL; struct cil_tree_node *false_node = NULL; struct cil_tree_node *tmp_node = NULL; cond_node_t *tmp_cond = NULL; cond_node_t *cond_node = NULL; int was_created; int swapped = CIL_FALSE; cond_av_list_t tmp_cl; tmp_cond = cond_node_create(pdb, NULL); if (tmp_cond == NULL) { rc = SEPOL_ERR; cil_tree_log(node, CIL_INFO, "Failed to create sepol conditional node"); goto exit; } rc = __cil_cond_expr_to_sepol_expr(pdb, cil_boolif->datum_expr, &tmp_cond->expr); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Failed to convert CIL conditional expression to sepol expression"); goto exit; } tmp_cond->true_list = &tmp_cl; rc = cond_normalize_expr(pdb, tmp_cond); if (rc != SEPOL_OK) { goto exit; } if (tmp_cond->false_list != NULL) { tmp_cond->true_list = NULL; swapped = CIL_TRUE; } cond_node = cond_node_find(pdb, tmp_cond, pdb->cond_list, &was_created); if (cond_node == NULL) { rc = SEPOL_ERR; goto exit; } if (was_created) { cond_node->next = pdb->cond_list; pdb->cond_list = cond_node; } cond_expr_destroy(tmp_cond->expr); free(tmp_cond); tmp_cond = NULL; for (cb_node = node->cl_head; cb_node != NULL; cb_node = cb_node->next) { if (cb_node->flavor == CIL_CONDBLOCK) { struct cil_condblock *cb = cb_node->data; if (cb->flavor == CIL_CONDTRUE) { true_node = cb_node; } else if (cb->flavor == CIL_CONDFALSE) { false_node = cb_node; } } } if (swapped) { tmp_node = true_node; true_node = false_node; false_node = tmp_node; } bool_args.db = db; bool_args.pdb = pdb; bool_args.cond_node = cond_node; bool_args.filename_trans_table = filename_trans_table; if (true_node != NULL) { bool_args.cond_flavor = CIL_CONDTRUE; rc = cil_tree_walk(true_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); if (rc != SEPOL_OK) { cil_tree_log(true_node, CIL_ERR, "Failure while walking true conditional block"); goto exit; } } if (false_node != NULL) { bool_args.cond_flavor = CIL_CONDFALSE; rc = cil_tree_walk(false_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); if (rc != SEPOL_OK) { cil_tree_log(false_node, CIL_ERR, "Failure while walking false conditional block"); goto exit; } } return SEPOL_OK; exit: if (tmp_cond) { if (tmp_cond->expr) cond_expr_destroy(tmp_cond->expr); free(tmp_cond); } return rc; } int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roletransition *roletrans, hashtab_t role_trans_table) { int rc = SEPOL_ERR; role_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list; role_datum_t *sepol_result = NULL; role_trans_t *new = NULL; uint32_t *new_role = NULL; ebitmap_t role_bitmap, type_bitmap; ebitmap_node_t *rnode, *tnode; unsigned int i, j; struct cil_list_item *c; rc = __cil_expand_role(DATUM(roletrans->src), &role_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_type(roletrans->tgt, &type_bitmap); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(roletrans->obj); rc = __cil_get_sepol_role_datum(pdb, DATUM(roletrans->result), &sepol_result); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&role_bitmap, rnode, i) { if (!ebitmap_get_bit(&role_bitmap, i)) continue; rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&type_bitmap, tnode, j) { if (!ebitmap_get_bit(&type_bitmap, j)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; cil_list_for_each(c, class_list) { int add = CIL_TRUE; rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; new = cil_malloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->role = sepol_src->s.value; new->type = sepol_tgt->s.value; new->tclass = sepol_obj->s.value; new->new_role = sepol_result->s.value; rc = hashtab_insert(role_trans_table, (hashtab_key_t)new, &(new->new_role)); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { add = CIL_FALSE; new_role = hashtab_search(role_trans_table, (hashtab_key_t)new); if (new->new_role != *new_role) { cil_log(CIL_ERR, "Conflicting role transition rules\n"); } else { rc = SEPOL_OK; } } else { cil_log(CIL_ERR, "Out of memory\n"); } } if (add == CIL_TRUE) { new->next = pdb->role_tr; pdb->role_tr = new; } else { free(new); if (rc != SEPOL_OK) { goto exit; } } } } } rc = SEPOL_OK; exit: ebitmap_destroy(&role_bitmap); ebitmap_destroy(&type_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_roleallow_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roleallow *roleallow) { int rc = SEPOL_ERR; role_datum_t *sepol_src = NULL; role_datum_t *sepol_tgt = NULL; role_allow_t *sepol_roleallow = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; rc = __cil_expand_role(roleallow->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_role(roleallow->tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&src_bitmap, node1, i) { if (!ebitmap_get_bit(&src_bitmap, i)) continue; rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&tgt_bitmap, node2, j) { if (!ebitmap_get_bit(&tgt_bitmap, j)) continue; rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; sepol_roleallow = cil_malloc(sizeof(*sepol_roleallow)); memset(sepol_roleallow, 0, sizeof(role_allow_t)); sepol_roleallow->role = sepol_src->s.value; sepol_roleallow->new_role = sepol_tgt->s.value; sepol_roleallow->next = pdb->role_allow; pdb->role_allow = sepol_roleallow; } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); return rc; } int __cil_constrain_expr_datum_to_sepol_expr(policydb_t *pdb, const struct cil_db *db, struct cil_list_item *item, enum cil_flavor expr_flavor, constraint_expr_t *expr) { int rc = SEPOL_ERR; if (expr_flavor == CIL_USER) { user_datum_t *sepol_user = NULL; ebitmap_t user_bitmap; ebitmap_node_t *unode; unsigned int i; rc = __cil_expand_user(item->data, &user_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&user_bitmap, unode, i) { if (!ebitmap_get_bit(&user_bitmap, i)) { continue; } rc = __cil_get_sepol_user_datum(pdb, DATUM(db->val_to_user[i]), &sepol_user); if (rc != SEPOL_OK) { ebitmap_destroy(&user_bitmap); goto exit; } if (ebitmap_set_bit(&expr->names, sepol_user->s.value - 1, 1)) { ebitmap_destroy(&user_bitmap); goto exit; } } ebitmap_destroy(&user_bitmap); } else if (expr_flavor == CIL_ROLE) { role_datum_t *sepol_role = NULL; ebitmap_t role_bitmap; ebitmap_node_t *rnode; unsigned int i; rc = __cil_expand_role(item->data, &role_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&role_bitmap, rnode, i) { if (!ebitmap_get_bit(&role_bitmap, i)) continue; rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role); if (rc != SEPOL_OK) { ebitmap_destroy(&role_bitmap); goto exit; } if (ebitmap_set_bit(&expr->names, sepol_role->s.value - 1, 1)) { ebitmap_destroy(&role_bitmap); goto exit; } } ebitmap_destroy(&role_bitmap); } else if (expr_flavor == CIL_TYPE) { type_datum_t *sepol_type = NULL; ebitmap_t type_bitmap; ebitmap_node_t *tnode; unsigned int i; if (pdb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) { rc = __cil_get_sepol_type_datum(pdb, item->data, &sepol_type); if (rc != SEPOL_OK) { if (FLAVOR(item->data) == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = item->data; if (!attr->keep) { rc = 0; } } } if (sepol_type) { rc = ebitmap_set_bit(&expr->type_names->types, sepol_type->s.value - 1, 1); } if (rc != SEPOL_OK) { goto exit; } } rc = __cil_expand_type(item->data, &type_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&type_bitmap, tnode, i) { if (!ebitmap_get_bit(&type_bitmap, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_type); if (rc != SEPOL_OK) { ebitmap_destroy(&type_bitmap); goto exit; } if (ebitmap_set_bit(&expr->names, sepol_type->s.value - 1, 1)) { ebitmap_destroy(&type_bitmap); goto exit; } } ebitmap_destroy(&type_bitmap); } else { goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db *db, struct cil_list_item *op_item, enum cil_flavor expr_flavor, constraint_expr_t *expr) { int rc = SEPOL_ERR; struct cil_list_item *l_item = op_item->next; struct cil_list_item *r_item = op_item->next->next; enum cil_flavor l_operand = (enum cil_flavor)l_item->data; switch (l_operand) { case CIL_CONS_U1: expr->attr = CEXPR_USER; break; case CIL_CONS_U2: expr->attr = CEXPR_USER | CEXPR_TARGET; break; case CIL_CONS_U3: expr->attr = CEXPR_USER | CEXPR_XTARGET; break; case CIL_CONS_R1: expr->attr = CEXPR_ROLE; break; case CIL_CONS_R2: expr->attr = CEXPR_ROLE | CEXPR_TARGET; break; case CIL_CONS_R3: expr->attr = CEXPR_ROLE | CEXPR_XTARGET; break; case CIL_CONS_T1: expr->attr = CEXPR_TYPE; break; case CIL_CONS_T2: expr->attr = CEXPR_TYPE | CEXPR_TARGET; break; case CIL_CONS_T3: expr->attr = CEXPR_TYPE | CEXPR_XTARGET; break; case CIL_CONS_L1: { enum cil_flavor r_operand = (enum cil_flavor)r_item->data; if (r_operand == CIL_CONS_L2) { expr->attr = CEXPR_L1L2; } else if (r_operand == CIL_CONS_H1) { expr->attr = CEXPR_L1H1; } else { expr->attr = CEXPR_L1H2; } break; } case CIL_CONS_L2: expr->attr = CEXPR_L2H2; break; case CIL_CONS_H1: { enum cil_flavor r_operand = (enum cil_flavor)r_item->data; if (r_operand == CIL_CONS_L2) { expr->attr = CEXPR_H1L2; } else { expr->attr = CEXPR_H1H2; } break; } default: goto exit; break; } if (r_item->flavor == CIL_CONS_OPERAND) { expr->expr_type = CEXPR_ATTR; } else { expr->expr_type = CEXPR_NAMES; if (r_item->flavor == CIL_DATUM) { rc = __cil_constrain_expr_datum_to_sepol_expr(pdb, db, r_item, expr_flavor, expr); if (rc != SEPOL_OK) { goto exit; } } else if (r_item->flavor == CIL_LIST) { struct cil_list *r_expr = r_item->data; struct cil_list_item *curr; cil_list_for_each(curr, r_expr) { rc = __cil_constrain_expr_datum_to_sepol_expr(pdb, db, curr, expr_flavor, expr); if (rc != SEPOL_OK) { goto exit; } } } else { rc = SEPOL_ERR; goto exit; } } return SEPOL_OK; exit: return rc; } int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_db *db, const struct cil_list *cil_expr, constraint_expr_t **head, constraint_expr_t **tail) { int rc = SEPOL_ERR; struct cil_list_item *item; enum cil_flavor flavor; constraint_expr_t *op, *h1, *h2, *t1, *t2; int is_leaf = CIL_FALSE; if (cil_expr == NULL) { return SEPOL_ERR; } item = cil_expr->head; flavor = cil_expr->flavor; op = cil_malloc(sizeof(constraint_expr_t)); rc = constraint_expr_init(op); if (rc != SEPOL_OK) { goto exit; } enum cil_flavor cil_op = (enum cil_flavor)item->data; switch (cil_op) { case CIL_NOT: op->expr_type = CEXPR_NOT; break; case CIL_AND: op->expr_type = CEXPR_AND; break; case CIL_OR: op->expr_type = CEXPR_OR; break; case CIL_EQ: op->op = CEXPR_EQ; is_leaf = CIL_TRUE; break; case CIL_NEQ: op->op = CEXPR_NEQ; is_leaf = CIL_TRUE; break; case CIL_CONS_DOM: op->op = CEXPR_DOM; is_leaf = CIL_TRUE; break; case CIL_CONS_DOMBY: op->op = CEXPR_DOMBY; is_leaf = CIL_TRUE; break; case CIL_CONS_INCOMP: op->op = CEXPR_INCOMP; is_leaf = CIL_TRUE; break; default: goto exit; } if (is_leaf == CIL_TRUE) { rc = __cil_constrain_expr_leaf_to_sepol_expr(pdb, db, item, flavor, op); if (rc != SEPOL_OK) { goto exit; } *head = op; *tail = op; } else if (cil_op == CIL_NOT) { struct cil_list *l_expr = item->next->data; rc = __cil_constrain_expr_to_sepol_expr_helper(pdb, db, l_expr, &h1, &t1); if (rc != SEPOL_OK) { goto exit; } t1->next = op; *head = h1; *tail = op; } else { struct cil_list *l_expr = item->next->data; struct cil_list *r_expr = item->next->next->data; rc = __cil_constrain_expr_to_sepol_expr_helper(pdb, db, l_expr, &h1, &t1); if (rc != SEPOL_OK) { goto exit; } rc = __cil_constrain_expr_to_sepol_expr_helper(pdb, db, r_expr, &h2, &t2); if (rc != SEPOL_OK) { constraint_expr_destroy(h1); goto exit; } t1->next = h2; t2->next = op; *head = h1; *tail = op; } return SEPOL_OK; exit: constraint_expr_destroy(op); return SEPOL_ERR; } int __cil_constrain_expr_to_sepol_expr(policydb_t *pdb, const struct cil_db *db, const struct cil_list *cil_expr, constraint_expr_t **sepol_expr) { int rc; constraint_expr_t *head, *tail; rc = __cil_constrain_expr_to_sepol_expr_helper(pdb, db, cil_expr, &head, &tail); if (rc != SEPOL_OK) { return SEPOL_ERR; } *sepol_expr = head; return SEPOL_OK; } int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *class, struct cil_list *perms, struct cil_list *expr) { int rc = SEPOL_ERR; constraint_node_t *sepol_constrain = NULL; constraint_expr_t *sepol_expr = NULL; class_datum_t *sepol_class = NULL; sepol_constrain = cil_malloc(sizeof(*sepol_constrain)); memset(sepol_constrain, 0, sizeof(constraint_node_t)); rc = __cil_get_sepol_class_datum(pdb, class, &sepol_class); if (rc != SEPOL_OK) goto exit; rc = __cil_perms_to_datum(perms, sepol_class, &sepol_constrain->permissions); if (rc != SEPOL_OK) { goto exit; } rc = __cil_constrain_expr_to_sepol_expr(pdb, db, expr, &sepol_expr); if (rc != SEPOL_OK) { goto exit; } sepol_constrain->expr = sepol_expr; sepol_constrain->next = sepol_class->constraints; sepol_class->constraints = sepol_constrain; return SEPOL_OK; exit: free(sepol_constrain); return rc; } int cil_constrain_expand(policydb_t *pdb, const struct cil_db *db, struct cil_list *classperms, struct cil_list *expr) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = cil_constrain_to_policydb_helper(pdb, db, DATUM(cp->class), cp->perms, expr); if (rc != SEPOL_OK) { goto exit; } } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = cil_constrain_expand(pdb, db, cmp->classperms, expr); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = cil_constrain_expand(pdb, db, cp->classperms, expr); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_constrain_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_constrain *cil_constrain) { int rc = SEPOL_ERR; rc = cil_constrain_expand(pdb, db, cil_constrain->classperms, cil_constrain->datum_expr); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert constraint into policydb\n"); return rc; } int cil_validatetrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_validatetrans *cil_validatetrans) { int rc = SEPOL_ERR; struct cil_list *expr = cil_validatetrans->datum_expr; class_datum_t *sepol_class = NULL; struct cil_list *class_list; constraint_node_t *sepol_validatetrans = NULL; constraint_expr_t *sepol_expr = NULL; struct cil_list_item *c; class_list = cil_expand_class(cil_validatetrans->class); cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; sepol_validatetrans = cil_malloc(sizeof(*sepol_validatetrans)); memset(sepol_validatetrans, 0, sizeof(constraint_node_t)); rc = __cil_constrain_expr_to_sepol_expr(pdb, db, expr, &sepol_expr); if (rc != SEPOL_OK) { free(sepol_validatetrans); goto exit; } sepol_validatetrans->expr = sepol_expr; sepol_validatetrans->next = sepol_class->validatetrans; sepol_class->validatetrans = sepol_validatetrans; } rc = SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return rc; } int __cil_cats_to_mls_level(policydb_t *pdb, struct cil_cats *cats, mls_level_t *mls_level) { int rc = SEPOL_ERR; struct cil_list_item *i; cat_datum_t *sepol_cat = NULL; cil_list_for_each(i, cats->datum_expr) { struct cil_tree_node *node = DATUM(i->data)->nodes->head->data; if (node->flavor == CIL_CATSET) { struct cil_list_item *j; struct cil_catset *cs = i->data; cil_list_for_each(j, cs->cats->datum_expr) { rc = __cil_get_sepol_cat_datum(pdb, j->data, &sepol_cat); if (rc != SEPOL_OK) goto exit; rc = ebitmap_set_bit(&mls_level->cat, sepol_cat->s.value - 1, 1); if (rc != SEPOL_OK) goto exit; } } else { rc = __cil_get_sepol_cat_datum(pdb, i->data, &sepol_cat); if (rc != SEPOL_OK) goto exit; rc = ebitmap_set_bit(&mls_level->cat, sepol_cat->s.value - 1, 1); if (rc != SEPOL_OK) goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } int cil_sepol_level_define(policydb_t *pdb, struct cil_sens *cil_sens) { int rc = SEPOL_ERR; struct cil_list_item *curr; level_datum_t *sepol_level = NULL; mls_level_t *mls_level = NULL; rc = __cil_get_sepol_level_datum(pdb, DATUM(cil_sens), &sepol_level); if (rc != SEPOL_OK) goto exit; mls_level = sepol_level->level; ebitmap_init(&mls_level->cat); if (cil_sens->cats_list) { cil_list_for_each(curr, cil_sens->cats_list) { struct cil_cats *cats = curr->data; rc = __cil_cats_to_mls_level(pdb, cats, mls_level); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to insert category set into sepol mls level\n"); goto exit; } } } sepol_level->defined = 1; return SEPOL_OK; exit: return rc; } int cil_level_to_mls_level(policydb_t *pdb, struct cil_level *cil_level, mls_level_t *mls_level) { int rc = SEPOL_ERR; struct cil_sens *cil_sens = cil_level->sens; struct cil_cats *cats = cil_level->cats; level_datum_t *sepol_level = NULL; rc = __cil_get_sepol_level_datum(pdb, DATUM(cil_sens), &sepol_level); if (rc != SEPOL_OK) goto exit; mls_level->sens = sepol_level->level->sens; ebitmap_init(&mls_level->cat); if (cats != NULL) { rc = __cil_cats_to_mls_level(pdb, cats, mls_level); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to insert category set into sepol mls level\n"); goto exit; } } rc = SEPOL_OK; exit: return rc; } int __cil_levelrange_to_mls_range(policydb_t *pdb, struct cil_levelrange *cil_lvlrange, mls_range_t *mls_range) { int rc = SEPOL_ERR; struct cil_level *low = cil_lvlrange->low; struct cil_level *high = cil_lvlrange->high; mls_level_t *mls_level = NULL; mls_level = &mls_range->level[0]; rc = cil_level_to_mls_level(pdb, low, mls_level); if (rc != SEPOL_OK) { goto exit; } mls_level = &mls_range->level[1]; rc = cil_level_to_mls_level(pdb, high, mls_level); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_userlevel_userrange_to_policydb(policydb_t *pdb, struct cil_user *cil_user) { int rc = SEPOL_ERR; struct cil_level *cil_level = cil_user->dftlevel; struct cil_levelrange *cil_levelrange = cil_user->range; user_datum_t *sepol_user = NULL; rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_user), &sepol_user); if (rc != SEPOL_OK) goto exit; rc = cil_level_to_mls_level(pdb, cil_level, &sepol_user->exp_dfltlevel); if (rc != SEPOL_OK) { goto exit; } rc = __cil_levelrange_to_mls_range(pdb, cil_levelrange, &sepol_user->exp_range); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int __cil_context_to_sepol_context(policydb_t *pdb, struct cil_context *cil_context, context_struct_t *sepol_context) { int rc = SEPOL_ERR; struct cil_levelrange *cil_lvlrange = cil_context->range; user_datum_t *sepol_user = NULL; role_datum_t *sepol_role = NULL; type_datum_t *sepol_type = NULL; rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_context->user), &sepol_user); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_role_datum(pdb, DATUM(cil_context->role), &sepol_role); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_context->type), &sepol_type); if (rc != SEPOL_OK) goto exit; sepol_context->user = sepol_user->s.value; sepol_context->role = sepol_role->s.value; sepol_context->type = sepol_type->s.value; if (pdb->mls == CIL_TRUE) { mls_context_init(sepol_context); rc = __cil_levelrange_to_mls_range(pdb, cil_lvlrange, &sepol_context->range); if (rc != SEPOL_OK) { cil_log(CIL_ERR,"Problem with MLS\n"); mls_context_destroy(sepol_context); goto exit; } } return SEPOL_OK; exit: return rc; } int cil_sidorder_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; unsigned count = 0; ocontext_t *tail = NULL; if (db->sidorder == NULL || db->sidorder->head == NULL) { cil_log(CIL_WARN, "No sidorder statement in policy\n"); return SEPOL_OK; } cil_list_for_each(curr, db->sidorder) { struct cil_sid *cil_sid = (struct cil_sid*)curr->data; struct cil_context *cil_context = cil_sid->context; if (cil_context != NULL) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_ISID], &tail); count++; new_ocon->sid[0] = count; new_ocon->u.name = cil_strdup(cil_sid->datum.fqn); rc = __cil_context_to_sepol_context(pdb, cil_context, &new_ocon->context[0]); if (rc != SEPOL_OK) { cil_log(CIL_ERR,"Problem with context for SID %s\n",cil_sid->datum.fqn); goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_rangetransition *rangetrans, hashtab_t range_trans_table) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_class = NULL; struct cil_list *class_list; range_trans_t *newkey = NULL; struct mls_range *newdatum = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; struct cil_list_item *c; struct mls_range *o_range = NULL; rc = __cil_expand_type(rangetrans->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_type(rangetrans->exec, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(rangetrans->obj); ebitmap_for_each_bit(&src_bitmap, node1, i) { if (!ebitmap_get_bit(&src_bitmap, i)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_bit(&tgt_bitmap, node2, j) { if (!ebitmap_get_bit(&tgt_bitmap, j)) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; cil_list_for_each(c, class_list) { int add = CIL_TRUE; rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; newkey = cil_calloc(1, sizeof(*newkey)); newdatum = cil_calloc(1, sizeof(*newdatum)); newkey->source_type = sepol_src->s.value; newkey->target_type = sepol_tgt->s.value; newkey->target_class = sepol_class->s.value; rc = __cil_levelrange_to_mls_range(pdb, rangetrans->range, newdatum); if (rc != SEPOL_OK) { free(newkey); free(newdatum); goto exit; } rc = hashtab_insert(range_trans_table, (hashtab_key_t)newkey, newdatum); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { add = CIL_FALSE; o_range = hashtab_search(range_trans_table, (hashtab_key_t)newkey); if (!mls_range_eq(newdatum, o_range)) { cil_log(CIL_ERR, "Conflicting Range transition rules\n"); } else { rc = SEPOL_OK; } } else { cil_log(CIL_ERR, "Out of memory\n"); } } if (add == CIL_TRUE) { rc = hashtab_insert(pdb->range_tr, (hashtab_key_t)newkey, newdatum); if (rc != SEPOL_OK) { mls_range_destroy(newdatum); free(newdatum); free(newkey); cil_log(CIL_ERR, "Out of memory\n"); goto exit; } } else { mls_range_destroy(newdatum); free(newdatum); free(newkey); if (rc != SEPOL_OK) { goto exit; } } } } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; struct in6_addr subnet_prefix; for (i = 0; i < ibpkeycons->count; i++) { struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i]; ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBPKEY], &tail); rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, &subnet_prefix); if (rc != 1) { cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid IPV6 format\n"); rc = SEPOL_ERR; goto exit; } memcpy(&new_ocon->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0], sizeof(new_ocon->u.ibpkey.subnet_prefix)); new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low; new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high; rc = __cil_context_to_sepol_context(pdb, cil_ibpkeycon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < portcons->count; i++) { struct cil_portcon *cil_portcon = portcons->array[i]; ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_PORT], &tail); switch (cil_portcon->proto) { case CIL_PROTOCOL_UDP: new_ocon->u.port.protocol = IPPROTO_UDP; break; case CIL_PROTOCOL_TCP: new_ocon->u.port.protocol = IPPROTO_TCP; break; case CIL_PROTOCOL_DCCP: new_ocon->u.port.protocol = IPPROTO_DCCP; break; case CIL_PROTOCOL_SCTP: new_ocon->u.port.protocol = IPPROTO_SCTP; break; default: /* should not get here */ rc = SEPOL_ERR; goto exit; } new_ocon->u.port.low_port = cil_portcon->port_low; new_ocon->u.port.high_port = cil_portcon->port_high; rc = __cil_context_to_sepol_context(pdb, cil_portcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_netifcon_to_policydb(policydb_t *pdb, struct cil_sort *netifcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < netifcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NETIF], &tail); struct cil_netifcon *cil_netifcon = netifcons->array[i]; new_ocon->u.name = cil_strdup(cil_netifcon->interface_str); rc = __cil_context_to_sepol_context(pdb, cil_netifcon->if_context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } rc = __cil_context_to_sepol_context(pdb, cil_netifcon->packet_context, &new_ocon->context[1]); if (rc != SEPOL_OK) { context_destroy(&new_ocon->context[0]); goto exit; } } return SEPOL_OK; exit: return rc; } int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *ibendportcons) { int rc = SEPOL_ERR; uint32_t i; ocontext_t *tail = NULL; for (i = 0; i < ibendportcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBENDPORT], &tail); struct cil_ibendportcon *cil_ibendportcon = ibendportcons->array[i]; new_ocon->u.ibendport.dev_name = cil_strdup(cil_ibendportcon->dev_name_str); new_ocon->u.ibendport.port = cil_ibendportcon->port; rc = __cil_context_to_sepol_context(pdb, cil_ibendportcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; ocontext_t *tail6 = NULL; for (i = 0; i < nodecons->count; i++) { ocontext_t *new_ocon = NULL; struct cil_nodecon *cil_nodecon = nodecons->array[i]; if (cil_nodecon->addr->family == AF_INET) { new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NODE], &tail); new_ocon->u.node.addr = cil_nodecon->addr->ip.v4.s_addr; new_ocon->u.node.mask = cil_nodecon->mask->ip.v4.s_addr; } else if (cil_nodecon->addr->family == AF_INET6) { new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NODE6], &tail6); memcpy(new_ocon->u.node6.addr, &cil_nodecon->addr->ip.v6.s6_addr[0], 16); memcpy(new_ocon->u.node6.mask, &cil_nodecon->mask->ip.v6.s6_addr[0], 16); } else { /* should not get here */ rc = SEPOL_ERR; goto exit; } rc = __cil_context_to_sepol_context(pdb, cil_nodecon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_fsuse_to_policydb(policydb_t *pdb, struct cil_sort *fsuses) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < fsuses->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_FSUSE], &tail); struct cil_fsuse *cil_fsuse = fsuses->array[i]; new_ocon->u.name = cil_strdup(cil_fsuse->fs_str); new_ocon->v.behavior = cil_fsuse->type; rc = __cil_context_to_sepol_context(pdb, cil_fsuse->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons) { int rc = SEPOL_ERR; uint32_t i = 0; genfs_t *genfs_tail = NULL; ocontext_t *ocon_tail = NULL; for (i = 0; i < genfscons->count; i++) { struct cil_genfscon *cil_genfscon = genfscons->array[i]; ocontext_t *new_ocon = cil_malloc(sizeof(ocontext_t)); memset(new_ocon, 0, sizeof(ocontext_t)); if (genfs_tail && strcmp(genfs_tail->fstype, cil_genfscon->fs_str) == 0) { ocon_tail->next = new_ocon; } else { genfs_t *new_genfs = cil_malloc(sizeof(genfs_t)); memset(new_genfs, 0, sizeof(genfs_t)); new_genfs->fstype = cil_strdup(cil_genfscon->fs_str); new_genfs->head = new_ocon; if (genfs_tail) { genfs_tail->next = new_genfs; } else { pdb->genfs = new_genfs; } genfs_tail = new_genfs; } ocon_tail = new_ocon; new_ocon->u.name = cil_strdup(cil_genfscon->path_str); rc = __cil_context_to_sepol_context(pdb, cil_genfscon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_pirqcon_to_policydb(policydb_t *pdb, struct cil_sort *pirqcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < pirqcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_PIRQ], &tail); struct cil_pirqcon *cil_pirqcon = pirqcons->array[i]; new_ocon->u.pirq = cil_pirqcon->pirq; rc = __cil_context_to_sepol_context(pdb, cil_pirqcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_iomemcon_to_policydb(policydb_t *pdb, struct cil_sort *iomemcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < iomemcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_IOMEM], &tail); struct cil_iomemcon *cil_iomemcon = iomemcons->array[i]; new_ocon->u.iomem.low_iomem = cil_iomemcon->iomem_low; new_ocon->u.iomem.high_iomem = cil_iomemcon->iomem_high; rc = __cil_context_to_sepol_context(pdb, cil_iomemcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_ioportcon_to_policydb(policydb_t *pdb, struct cil_sort *ioportcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < ioportcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_IOPORT], &tail); struct cil_ioportcon *cil_ioportcon = ioportcons->array[i]; new_ocon->u.ioport.low_ioport = cil_ioportcon->ioport_low; new_ocon->u.ioport.high_ioport = cil_ioportcon->ioport_high; rc = __cil_context_to_sepol_context(pdb, cil_ioportcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_pcidevicecon_to_policydb(policydb_t *pdb, struct cil_sort *pcidevicecons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < pcidevicecons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_PCIDEVICE], &tail); struct cil_pcidevicecon *cil_pcidevicecon = pcidevicecons->array[i]; new_ocon->u.device = cil_pcidevicecon->dev; rc = __cil_context_to_sepol_context(pdb, cil_pcidevicecon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_devicetreecon_to_policydb(policydb_t *pdb, struct cil_sort *devicetreecons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < devicetreecons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_DEVICETREE], &tail); struct cil_devicetreecon *cil_devicetreecon = devicetreecons->array[i]; new_ocon->u.name = cil_strdup(cil_devicetreecon->path); rc = __cil_context_to_sepol_context(pdb, cil_devicetreecon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def) { struct cil_list_item *curr; class_datum_t *sepol_class; struct cil_list *class_list; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; class_list = cil_expand_class(curr->data); cil_list_for_each(c, class_list) { int rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; switch (def->flavor) { case CIL_DEFAULTUSER: if (!sepol_class->default_user) { sepol_class->default_user = def->object; } else if (sepol_class->default_user != (char)def->object) { cil_log(CIL_ERR,"User default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; case CIL_DEFAULTROLE: if (!sepol_class->default_role) { sepol_class->default_role = def->object; } else if (sepol_class->default_role != (char)def->object) { cil_log(CIL_ERR,"Role default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; case CIL_DEFAULTTYPE: if (!sepol_class->default_type) { sepol_class->default_type = def->object; } else if (sepol_class->default_type != (char)def->object) { cil_log(CIL_ERR,"Type default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; default: goto exit; } } cil_list_destroy(&class_list, CIL_FALSE); } return SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return SEPOL_ERR; } int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def) { struct cil_list_item *curr; class_datum_t *sepol_class; struct cil_list *class_list; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; class_list = cil_expand_class(curr->data); cil_list_for_each(c, class_list) { int rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; if (!sepol_class->default_range) { sepol_class->default_range = def->object_range; } else if (sepol_class->default_range != (char)def->object_range) { cil_log(CIL_ERR,"Range default labeling for class %s already specified\n", DATUM(curr->data)->fqn); goto exit; } } cil_list_destroy(&class_list, CIL_FALSE); } return SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return SEPOL_ERR; } int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args) { int rc = SEPOL_OK; int pass; struct cil_args_binary *args = extra_args; const struct cil_db *db; policydb_t *pdb; hashtab_t filename_trans_table; hashtab_t range_trans_table; hashtab_t role_trans_table; void **type_value_to_cil; db = args->db; pdb = args->pdb; pass = args->pass; filename_trans_table = args->filename_trans_table; range_trans_table = args->range_trans_table; role_trans_table = args->role_trans_table; type_value_to_cil = args->type_value_to_cil; if (node->flavor >= CIL_MIN_DECLARATIVE) { if (node != DATUM(node->data)->nodes->head->data) { goto exit; } } switch (pass) { case 1: switch (node->flavor) { case CIL_ROLE: rc = cil_role_to_policydb(pdb, node->data); break; case CIL_TYPE: rc = cil_type_to_policydb(pdb, node->data, type_value_to_cil); break; case CIL_TYPEATTRIBUTE: rc = cil_typeattribute_to_policydb(pdb, node->data, type_value_to_cil); break; case CIL_POLICYCAP: rc = cil_policycap_to_policydb(pdb, node->data); break; case CIL_USER: rc = cil_user_to_policydb(pdb, node->data); break; case CIL_BOOL: rc = cil_bool_to_policydb(pdb, node->data); break; case CIL_CATALIAS: if (pdb->mls == CIL_TRUE) { rc = cil_catalias_to_policydb(pdb, node->data); } break; case CIL_SENS: if (pdb->mls == CIL_TRUE) { rc = cil_sepol_level_define(pdb, node->data); } break; default: break; } break; case 2: switch (node->flavor) { case CIL_TYPE: rc = cil_type_bounds_to_policydb(pdb, node->data); break; case CIL_TYPEALIAS: rc = cil_typealias_to_policydb(pdb, node->data); break; case CIL_TYPEPERMISSIVE: rc = cil_typepermissive_to_policydb(pdb, node->data); break; case CIL_TYPEATTRIBUTE: rc = cil_typeattribute_to_bitmap(pdb, db, node->data); break; case CIL_SENSALIAS: if (pdb->mls == CIL_TRUE) { rc = cil_sensalias_to_policydb(pdb, node->data); } break; case CIL_ROLE: rc = cil_role_bounds_to_policydb(pdb, node->data); if (rc != SEPOL_OK) goto exit; rc = cil_roletype_to_policydb(pdb, db, node->data); break; case CIL_USER: rc = cil_user_bounds_to_policydb(pdb, node->data); if (rc != SEPOL_OK) goto exit; if (pdb->mls == CIL_TRUE) { rc = cil_userlevel_userrange_to_policydb(pdb, node->data); if (rc != SEPOL_OK) { goto exit; } } rc = cil_userrole_to_policydb(pdb, db, node->data); break; case CIL_TYPE_RULE: rc = cil_type_rule_to_policydb(pdb, db, node->data); break; case CIL_AVRULE: case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (db->disable_neverallow != CIL_TRUE && rule->rule_kind == CIL_AVRULE_NEVERALLOW) { struct cil_list *neverallows = args->neverallows; cil_list_prepend(neverallows, CIL_LIST_ITEM, node); } break; } case CIL_ROLETRANSITION: rc = cil_roletrans_to_policydb(pdb, db, node->data, role_trans_table); break; case CIL_ROLEATTRIBUTESET: /*rc = cil_roleattributeset_to_policydb(pdb, node->data);*/ break; case CIL_NAMETYPETRANSITION: rc = cil_typetransition_to_policydb(pdb, db, node->data, filename_trans_table); break; case CIL_CONSTRAIN: rc = cil_constrain_to_policydb(pdb, db, node->data); break; case CIL_MLSCONSTRAIN: if (pdb->mls == CIL_TRUE) { rc = cil_constrain_to_policydb(pdb, db, node->data); } break; case CIL_VALIDATETRANS: rc = cil_validatetrans_to_policydb(pdb, db, node->data); break; case CIL_MLSVALIDATETRANS: if (pdb->mls == CIL_TRUE) { rc = cil_validatetrans_to_policydb(pdb, db, node->data); } break; case CIL_RANGETRANSITION: if (pdb->mls == CIL_TRUE) { rc = cil_rangetransition_to_policydb(pdb, db, node->data, range_trans_table); } break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: rc = cil_default_to_policydb(pdb, node->data); break; case CIL_DEFAULTRANGE: rc = cil_defaultrange_to_policydb(pdb, node->data); break; default: break; } break; case 3: switch (node->flavor) { case CIL_BOOLEANIF: rc = cil_booleanif_to_policydb(pdb, db, node, filename_trans_table); break; case CIL_AVRULE: { struct cil_avrule *rule = node->data; if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) { rc = cil_avrule_to_policydb(pdb, db, node->data); } } break; case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) { rc = cil_avrulex_to_hashtable(pdb, db, node->data, args); } } break; case CIL_ROLEALLOW: rc = cil_roleallow_to_policydb(pdb, db, node->data); break; default: break; } default: break; } exit: if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Binary policy creation failed"); } return rc; } int __cil_binary_create_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } else if (node->flavor == CIL_BOOLEANIF) { *finished = CIL_TREE_SKIP_HEAD; } rc = __cil_node_to_policydb(node, extra_args); if (rc != SEPOL_OK) { goto exit; } exit: return rc; } int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_portcon_to_policydb(pdb, db->portcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_netifcon_to_policydb(pdb, db->netifcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_nodecon_to_policydb(pdb, db->nodecon); if (rc != SEPOL_OK) { goto exit; } rc = cil_fsuse_to_policydb(pdb, db->fsuse); if (rc != SEPOL_OK) { goto exit; } rc = cil_genfscon_to_policydb(pdb, db->genfscon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ibpkeycon_to_policydb(pdb, db->ibpkeycon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ibendportcon_to_policydb(pdb, db->ibendportcon); if (rc != SEPOL_OK) { goto exit; } if (db->target_platform == SEPOL_TARGET_XEN) { rc = cil_pirqcon_to_policydb(pdb, db->pirqcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_iomemcon_to_policydb(pdb, db->iomemcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ioportcon_to_policydb(pdb, db->ioportcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_pcidevicecon_to_policydb(pdb, db->pcidevicecon); if (rc != SEPOL_OK) { goto exit; } rc = cil_devicetreecon_to_policydb(pdb, db->devicetreecon); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int __cil_common_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; common_datum_t *common = (common_datum_t *)datum; if (common->s.value < 1 || common->s.value > pdb->p_commons.nprim) { return -EINVAL; } pdb->p_common_val_to_name[common->s.value - 1] = (char *)key; return 0; } int __cil_class_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; class_datum_t *class = (class_datum_t *)datum; if (class->s.value < 1 || class->s.value > pdb->p_classes.nprim) { return -EINVAL; } pdb->p_class_val_to_name[class->s.value - 1] = (char *)key; pdb->class_val_to_struct[class->s.value - 1] = class; return 0; } int __cil_role_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; role_datum_t *role = (role_datum_t *)datum; if (role->s.value < 1 || role->s.value > pdb->p_roles.nprim) { return -EINVAL; } pdb->p_role_val_to_name[role->s.value - 1] = (char *)key; pdb->role_val_to_struct[role->s.value - 1] = role; return 0; } int __cil_type_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; type_datum_t *type = (type_datum_t *)datum; if (type->s.value < 1 || type->s.value > pdb->p_types.nprim) { return -EINVAL; } pdb->p_type_val_to_name[type->s.value - 1] = (char *)key; pdb->type_val_to_struct[type->s.value - 1] = type; return 0; } int __cil_user_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; user_datum_t *user = (user_datum_t *)datum; if (user->s.value < 1 || user->s.value > pdb->p_users.nprim) { return -EINVAL; } pdb->p_user_val_to_name[user->s.value - 1] = (char *)key; pdb->user_val_to_struct[user->s.value - 1] = user; return 0; } int __cil_bool_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; cond_bool_datum_t *bool = (cond_bool_datum_t *)datum; if (bool->s.value < 1 || bool->s.value > pdb->p_bools.nprim) { return -EINVAL; } pdb->p_bool_val_to_name[bool->s.value - 1] = (char *)key; pdb->bool_val_to_struct[bool->s.value - 1] = bool; return 0; } int __cil_level_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; level_datum_t *level = (level_datum_t *)datum; if (level->level->sens < 1 || level->level->sens > pdb->p_levels.nprim) { return -EINVAL; } pdb->p_sens_val_to_name[level->level->sens - 1] = (char *)key; return 0; } int __cil_cat_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; cat_datum_t *cat = (cat_datum_t *)datum; if (cat->s.value < 1 || cat->s.value > pdb->p_cats.nprim) { return -EINVAL; } pdb->p_cat_val_to_name[cat->s.value - 1] = (char *)key; return 0; } int __cil_policydb_val_arrays_create(policydb_t *policydb) { int rc = SEPOL_ERR; policydb->p_common_val_to_name = cil_malloc(sizeof(char *) * policydb->p_commons.nprim); rc = hashtab_map(policydb->p_commons.table, &__cil_common_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_class_val_to_name = cil_malloc(sizeof(char *) * policydb->p_classes.nprim); policydb->class_val_to_struct = cil_malloc(sizeof(class_datum_t *) * policydb->p_classes.nprim); rc = hashtab_map(policydb->p_classes.table, &__cil_class_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_role_val_to_name = cil_malloc(sizeof(char *) * policydb->p_roles.nprim); policydb->role_val_to_struct = cil_malloc(sizeof(role_datum_t *) * policydb->p_roles.nprim); rc = hashtab_map(policydb->p_roles.table, &__cil_role_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_type_val_to_name = cil_malloc(sizeof(char *) * policydb->p_types.nprim); policydb->type_val_to_struct = cil_malloc(sizeof(type_datum_t *) * policydb->p_types.nprim); rc = hashtab_map(policydb->p_types.table, &__cil_type_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_user_val_to_name = cil_malloc(sizeof(char *) * policydb->p_users.nprim); policydb->user_val_to_struct = cil_malloc(sizeof(user_datum_t *) * policydb->p_users.nprim); rc = hashtab_map(policydb->p_users.table, &__cil_user_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_bool_val_to_name = cil_malloc(sizeof(char *) * policydb->p_bools.nprim); policydb->bool_val_to_struct = cil_malloc(sizeof(cond_bool_datum_t *) * policydb->p_bools.nprim); rc = hashtab_map(policydb->p_bools.table, &__cil_bool_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_sens_val_to_name = cil_malloc(sizeof(char *) * policydb->p_levels.nprim); rc = hashtab_map(policydb->p_levels.table, &__cil_level_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } policydb->p_cat_val_to_name = cil_malloc(sizeof(char *) * policydb->p_cats.nprim); rc = hashtab_map(policydb->p_cats.table, &__cil_cat_val_array_insert, policydb); if (rc != SEPOL_OK) { goto exit; } exit: return rc; } static void __cil_set_conditional_state_and_flags(policydb_t *pdb) { cond_node_t *cur; for (cur = pdb->cond_list; cur != NULL; cur = cur->next) { int new_state; cond_av_list_t *c; new_state = cond_evaluate_expr(pdb, cur->expr); cur->cur_state = new_state; if (new_state == -1) { cil_log(CIL_WARN, "Expression result was undefined - disabling all rules\n"); } for (c = cur->true_list; c != NULL; c = c->next) { if (new_state <= 0) { c->node->key.specified &= ~AVTAB_ENABLED; } else { c->node->key.specified |= AVTAB_ENABLED; } } for (c = cur->false_list; c != NULL; c = c->next) { if (new_state) { /* -1 or 1 */ c->node->key.specified &= ~AVTAB_ENABLED; } else { c->node->key.specified |= AVTAB_ENABLED; } } } } int __cil_policydb_create(const struct cil_db *db, struct sepol_policydb **spdb) { int rc; struct policydb *pdb = NULL; rc = sepol_policydb_create(spdb); if (rc < 0) { cil_log(CIL_ERR, "Failed to create policy db\n"); // spdb could be a dangling pointer at this point, so reset it so // callers of this function don't need to worry about freeing garbage *spdb = NULL; goto exit; } pdb = &(*spdb)->p; pdb->policy_type = POLICY_KERN; pdb->target_platform = db->target_platform; pdb->policyvers = db->policy_version; pdb->handle_unknown = db->handle_unknown; pdb->mls = db->mls; return SEPOL_OK; exit: return rc; } int __cil_policydb_init(policydb_t *pdb, const struct cil_db *db, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; // these flags should get set in __cil_policydb_create. However, for // backwards compatability, it is possible that __cil_policydb_create is // never called. So, they must also be set here. pdb->handle_unknown = db->handle_unknown; pdb->mls = db->mls; rc = cil_classorder_to_policydb(pdb, db, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { goto exit; } if (pdb->mls == CIL_TRUE) { rc = cil_catorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } rc = cil_sensitivityorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } } rc = avtab_alloc(&pdb->te_avtab, MAX_AVTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } rc = avtab_alloc(&pdb->te_cond_avtab, MAX_AVTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static unsigned int filename_trans_hash(hashtab_t h, const_hashtab_key_t key) { const filename_trans_t *k = (const filename_trans_t *)key; return ((k->tclass + (k->ttype << 2) + (k->stype << 9)) & (h->size - 1)); } static int filename_trans_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const filename_trans_t *a = (const filename_trans_t *)key1; const filename_trans_t *b = (const filename_trans_t *)key2; return a->stype != b->stype || a->ttype != b->ttype || a->tclass != b->tclass || strcmp(a->name, b->name); } static unsigned int range_trans_hash(hashtab_t h, const_hashtab_key_t key) { const range_trans_t *k = (const range_trans_t *)key; return ((k->target_class + (k->target_type << 2) + (k->source_type << 5)) & (h->size - 1)); } static int range_trans_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const range_trans_t *a = (const range_trans_t *)key1; const range_trans_t *b = (const range_trans_t *)key2; return a->source_type != b->source_type || a->target_type != b->target_type || a->target_class != b->target_class; } static unsigned int role_trans_hash(hashtab_t h, const_hashtab_key_t key) { const role_trans_t *k = (const role_trans_t *)key; return ((k->role + (k->type << 2) + (k->tclass << 5)) & (h->size - 1)); } static int role_trans_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const role_trans_t *a = (const role_trans_t *)key1; const role_trans_t *b = (const role_trans_t *)key2; return a->role != b->role || a->type != b->type || a->tclass != b->tclass; } /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hashtab_key_t key) { const avtab_key_t *k = (const avtab_key_t *)key; static const uint32_t c1 = 0xcc9e2d51; static const uint32_t c2 = 0x1b873593; static const uint32_t r1 = 15; static const uint32_t r2 = 13; static const uint32_t m = 5; static const uint32_t n = 0xe6546b64; uint32_t hash = 0; #define mix(input) { \ uint32_t v = input; \ v *= c1; \ v = (v << r1) | (v >> (32 - r1)); \ v *= c2; \ hash ^= v; \ hash = (hash << r2) | (hash >> (32 - r2)); \ hash = hash * m + n; \ } mix(k->target_class); mix(k->target_type); mix(k->source_type); mix(k->specified); #undef mix hash ^= hash >> 16; hash *= 0x85ebca6b; hash ^= hash >> 13; hash *= 0xc2b2ae35; hash ^= hash >> 16; return hash & (AVRULEX_TABLE_SIZE - 1); } static int avrulex_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const avtab_key_t *a = (const avtab_key_t *)key1; const avtab_key_t *b = (const avtab_key_t *)key2; return a->source_type != b->source_type || a->target_type != b->target_type || a->target_class != b->target_class || a->specified != b->specified; } int cil_binary_create(const struct cil_db *db, sepol_policydb_t **policydb) { int rc = SEPOL_ERR; struct sepol_policydb *pdb = NULL; rc = __cil_policydb_create(db, &pdb); if (rc != SEPOL_OK) { goto exit; } rc = cil_binary_create_allocated_pdb(db, pdb); if (rc != SEPOL_OK) { goto exit; } *policydb = pdb; return SEPOL_OK; exit: sepol_policydb_free(pdb); return rc; } static void __cil_destroy_sepol_class_perms(class_perm_node_t *curr) { class_perm_node_t *next; while (curr) { next = curr->next; free(curr); curr = next; } } static int __cil_rule_to_sepol_class_perms(policydb_t *pdb, struct cil_list *classperms, class_perm_node_t **sepol_class_perms) { int rc = SEPOL_ERR; struct cil_list_item *i; cil_list_for_each(i, classperms) { if (i->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i->data; if (FLAVOR(cp->class) == CIL_CLASS) { class_perm_node_t *cpn = NULL; class_datum_t *sepol_class = NULL; uint32_t data = 0; rc = __cil_get_sepol_class_datum(pdb, DATUM(cp->class), &sepol_class); if (rc != SEPOL_OK) goto exit; rc = __cil_perms_to_datum(cp->perms, sepol_class, &data); if (rc != SEPOL_OK) goto exit; if (data == 0) { /* No permissions */ return SEPOL_OK; } cpn = cil_malloc(sizeof(class_perm_node_t)); cpn->tclass = sepol_class->s.value; cpn->data = data; cpn->next = *sepol_class_perms; *sepol_class_perms = cpn; } else { /* MAP */ struct cil_list_item *j = NULL; cil_list_for_each(j, cp->perms) { struct cil_perm *cmp = j->data; rc = __cil_rule_to_sepol_class_perms(pdb, cmp->classperms, sepol_class_perms); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = i->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_rule_to_sepol_class_perms(pdb, cp->classperms, sepol_class_perms); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int __cil_permx_to_sepol_class_perms(policydb_t *pdb, struct cil_permissionx *permx, class_perm_node_t **sepol_class_perms) { int rc = SEPOL_OK; struct cil_list *class_list = NULL; struct cil_list_item *c; class_datum_t *sepol_obj = NULL; class_perm_node_t *cpn; uint32_t data = 0; char *perm_str = NULL; class_list = cil_expand_class(permx->obj); cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) { goto exit; } switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: perm_str = CIL_KEY_IOCTL; break; default: rc = SEPOL_ERR; goto exit; } rc = __perm_str_to_datum(perm_str, sepol_obj, &data); if (rc != SEPOL_OK) { goto exit; } cpn = cil_malloc(sizeof(*cpn)); cpn->tclass = sepol_obj->s.value; cpn->data = data; cpn->next = *sepol_class_perms; *sepol_class_perms = cpn; } exit: cil_list_destroy(&class_list, CIL_FALSE); return rc; } static void __cil_init_sepol_type_set(type_set_t *t) { ebitmap_init(&t->types); ebitmap_init(&t->negset); t->flags = 0; } static int __cil_add_sepol_type(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *datum, ebitmap_t *map) { int rc = SEPOL_ERR; struct cil_tree_node *n = datum->nodes->head->data; type_datum_t *sepol_datum = NULL; if (n->flavor == CIL_TYPEATTRIBUTE) { ebitmap_node_t *tnode; unsigned int i; struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; ebitmap_for_each_bit(attr->types, tnode, i) { if (!ebitmap_get_bit(attr->types, i)) continue; datum = DATUM(db->val_to_type[i]); rc = __cil_get_sepol_type_datum(pdb, datum, &sepol_datum); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(map, sepol_datum->s.value - 1, 1); } } else { rc = __cil_get_sepol_type_datum(pdb, datum, &sepol_datum); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(map, sepol_datum->s.value - 1, 1); } return SEPOL_OK; exit: return rc; } static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *node) { avrule_t *avrule; struct cil_tree_node *source_node; char *source_path; int is_cil; avrule = cil_malloc(sizeof(avrule_t)); avrule->specified = kind; avrule->flags = 0; __cil_init_sepol_type_set(&avrule->stypes); __cil_init_sepol_type_set(&avrule->ttypes); avrule->perms = NULL; avrule->line = node->line; avrule->source_filename = NULL; avrule->source_line = node->line; source_node = cil_tree_get_next_path(node, &source_path, &is_cil); if (source_node) { avrule->source_filename = source_path; if (!is_cil) { avrule->source_line = node->hll_line; } } avrule->next = NULL; return avrule; } static void __cil_destroy_sepol_avrules(avrule_t *curr) { avrule_t *next; while (curr) { next = curr->next; ebitmap_destroy(&curr->stypes.types); ebitmap_destroy(&curr->stypes.negset); ebitmap_destroy(&curr->ttypes.types); ebitmap_destroy(&curr->ttypes.negset); __cil_destroy_sepol_class_perms(curr->perms); free(curr); curr = next; } } static void __cil_print_parents(const char *pad, struct cil_tree_node *n) { if (!n) return; __cil_print_parents(pad, n->parent); if (n->flavor != CIL_SRC_INFO) { cil_tree_log(n, CIL_ERR,"%s%s", pad, cil_node_to_string(n)); } } static void __cil_print_classperm(struct cil_list *cp_list) { struct cil_list_item *i1, *i2; i1 = cp_list->head; if (i1->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i1->data; cil_log(CIL_ERR,"(%s (", DATUM(cp->class)->fqn); cil_list_for_each(i2, cp->perms) { cil_log(CIL_ERR,"%s",DATUM(i2->data)->fqn); if (i2 != cp->perms->tail) { cil_log(CIL_ERR," "); } else { cil_log(CIL_ERR,"))"); } } } else { struct cil_classperms_set *cp_set = i1->data; cil_log(CIL_ERR,"%s", DATUM(cp_set->set)->fqn); } } static void __cil_print_permissionx(struct cil_permissionx *px) { const char *kind_str = ""; char *expr_str; switch (px->kind) { case CIL_PERMX_KIND_IOCTL: kind_str = CIL_KEY_IOCTL; break; default: kind_str = "unknown"; break; } __cil_expr_to_string(px->expr_str, CIL_PERMISSIONX, &expr_str); cil_log(CIL_ERR, "%s %s (%s)", kind_str, DATUM(px->obj)->fqn, expr_str); free(expr_str); } static void __cil_print_rule(const char *pad, const char *kind, struct cil_avrule *avrule) { cil_log(CIL_ERR,"%s(%s ", pad, kind); cil_log(CIL_ERR,"%s %s ", DATUM(avrule->src)->fqn, DATUM(avrule->tgt)->fqn); if (!avrule->is_extended) { __cil_print_classperm(avrule->perms.classperms); } else { cil_log(CIL_ERR, "("); __cil_print_permissionx(avrule->perms.x.permx); cil_log(CIL_ERR, ")"); } cil_log(CIL_ERR,")\n"); } static int __cil_print_neverallow_failure(const struct cil_db *db, struct cil_tree_node *node) { int rc; struct cil_list_item *i2; struct cil_list *matching; struct cil_avrule *cil_rule = node->data; struct cil_avrule target; struct cil_tree_node *n2; struct cil_avrule *r2; char *neverallow_str; char *allow_str; enum cil_flavor avrule_flavor; target.rule_kind = CIL_AVRULE_ALLOWED; target.is_extended = cil_rule->is_extended; target.src = cil_rule->src; target.tgt = cil_rule->tgt; target.perms = cil_rule->perms; if (!cil_rule->is_extended) { neverallow_str = CIL_KEY_NEVERALLOW; allow_str = CIL_KEY_ALLOW; avrule_flavor = CIL_AVRULE; } else { neverallow_str = CIL_KEY_NEVERALLOWX; allow_str = CIL_KEY_ALLOWX; avrule_flavor = CIL_AVRULEX; } cil_tree_log(node, CIL_ERR, "%s check failed", neverallow_str); __cil_print_rule(" ", neverallow_str, cil_rule); cil_list_init(&matching, CIL_NODE); rc = cil_find_matching_avrule_in_ast(db->ast->root, avrule_flavor, &target, matching, CIL_FALSE); if (rc) { cil_log(CIL_ERR, "Error occurred while checking %s rules\n", neverallow_str); cil_list_destroy(&matching, CIL_FALSE); goto exit; } cil_list_for_each(i2, matching) { n2 = i2->data; r2 = n2->data; __cil_print_parents(" ", n2); __cil_print_rule(" ", allow_str, r2); } cil_log(CIL_ERR,"\n"); cil_list_destroy(&matching, CIL_FALSE); exit: return rc; } static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct cil_tree_node *node, int *violation) { int rc = SEPOL_OK; struct cil_avrule *cil_rule = node->data; struct cil_symtab_datum *tgt = cil_rule->tgt; uint32_t kind; avrule_t *rule; struct cil_list *xperms = NULL; struct cil_list_item *item; if (!cil_rule->is_extended) { kind = AVRULE_NEVERALLOW; } else { kind = AVRULE_XPERMS_NEVERALLOW; } rule = __cil_init_sepol_avrule(kind, node); rule->next = NULL; rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->stypes.types); if (rc != SEPOL_OK) { goto exit; } if (tgt->fqn == CIL_KEY_SELF) { rule->flags = RULE_SELF; } else { rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types); if (rc != SEPOL_OK) { goto exit; } } if (!cil_rule->is_extended) { rc = __cil_rule_to_sepol_class_perms(pdb, cil_rule->perms.classperms, &rule->perms); if (rc != SEPOL_OK) { goto exit; } rc = check_assertion(pdb, rule); if (rc == CIL_TRUE) { *violation = CIL_TRUE; rc = __cil_print_neverallow_failure(db, node); if (rc != SEPOL_OK) { goto exit; } } } else { rc = __cil_permx_to_sepol_class_perms(pdb, cil_rule->perms.x.permx, &rule->perms); if (rc != SEPOL_OK) { goto exit; } rc = __cil_permx_bitmap_to_sepol_xperms_list(cil_rule->perms.x.permx->perms, &xperms); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(item, xperms) { rule->xperms = item->data; rc = check_assertion(pdb, rule); if (rc == CIL_TRUE) { *violation = CIL_TRUE; rc = __cil_print_neverallow_failure(db, node); if (rc != SEPOL_OK) { goto exit; } } } } exit: if (xperms != NULL) { cil_list_for_each(item, xperms) { free(item->data); item->data = NULL; } cil_list_destroy(&xperms, CIL_FALSE); } rule->xperms = NULL; __cil_destroy_sepol_avrules(rule); return rc; } static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows, int *violation) { int rc = SEPOL_OK; struct cil_list_item *item; cil_list_for_each(item, neverallows) { rc = cil_check_neverallow(db, pdb, item->data, violation); if (rc != SEPOL_OK) { goto exit; } } exit: return rc; } static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { struct cil_classperms *cp; struct cil_list *cp_list; class_datum_t *sepol_class = pdb->class_val_to_struct[class - 1]; unsigned i; cil_classperms_init(&cp); cp->class = class_value_to_cil[class]; if (!cp->class) goto exit; cil_list_init(&cp->perms, CIL_PERM); for (i = 0; i < sepol_class->permissions.nprim; i++) { struct cil_perm *perm; if ((data & (1 << i)) == 0) continue; perm = perm_value_to_cil[class][i+1]; if (!perm) goto exit; cil_list_append(cp->perms, CIL_PERM, perm); } cil_list_init(&cp_list, CIL_CLASSPERMS); cil_list_append(cp_list, CIL_CLASSPERMS, cp); return cp_list; exit: cil_destroy_classperms(cp); cil_log(CIL_ERR,"Failed to create CIL class-permissions from sepol values\n"); return NULL; } static int cil_avrule_from_sepol(policydb_t *pdb, avtab_ptr_t sepol_rule, struct cil_avrule *cil_rule, void *type_value_to_cil[], struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; avtab_key_t *k = &sepol_rule->key; avtab_datum_t *d = &sepol_rule->datum; cil_rule->src = type_value_to_cil[k->source_type]; if (!cil_rule->src) goto exit; cil_rule->tgt = type_value_to_cil[k->target_type]; if (!cil_rule->tgt) goto exit; cil_rule->perms.classperms = cil_classperms_from_sepol(pdb, k->target_class, d->data, class_value_to_cil, perm_value_to_cil); if (!cil_rule->perms.classperms) goto exit; return SEPOL_OK; exit: cil_log(CIL_ERR,"Failed to create CIL AV rule from sepol values\n"); return rc; } static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void *type_value_to_cil, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[], int *violation) { int rc = SEPOL_OK; int i; for (i = 0; i < db->num_types; i++) { type_datum_t *child; type_datum_t *parent; avtab_ptr_t bad = NULL; int numbad = 0; struct cil_type *t = db->val_to_type[i]; if (!t->bounds) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(t), &child); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, DATUM(t->bounds), &parent); if (rc != SEPOL_OK) goto exit; rc = bounds_check_type(NULL, pdb, child->s.value, parent->s.value, &bad, &numbad); if (rc != SEPOL_OK) goto exit; if (bad) { avtab_ptr_t cur; struct cil_avrule target; struct cil_tree_node *n1 = NULL; *violation = CIL_TRUE; target.is_extended = 0; target.rule_kind = CIL_AVRULE_ALLOWED; target.src_str = NULL; target.tgt_str = NULL; cil_log(CIL_ERR, "Child type %s exceeds bounds of parent %s\n", t->datum.fqn, t->bounds->datum.fqn); for (cur = bad; cur; cur = cur->next) { struct cil_list_item *i2; struct cil_list *matching; rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to convert sepol avrule to CIL\n"); goto exit; } __cil_print_rule(" ", "allow", &target); cil_list_init(&matching, CIL_NODE); rc = cil_find_matching_avrule_in_ast(db->ast->root, CIL_AVRULE, &target, matching, CIL_TRUE); if (rc) { cil_log(CIL_ERR, "Error occurred while checking type bounds\n"); cil_list_destroy(&matching, CIL_FALSE); cil_list_destroy(&target.perms.classperms, CIL_TRUE); bounds_destroy_bad(bad); goto exit; } cil_list_for_each(i2, matching) { struct cil_tree_node *n2 = i2->data; struct cil_avrule *r2 = n2->data; if (n1 == n2) { cil_log(CIL_ERR, " \n"); } else { n1 = n2; __cil_print_parents(" ", n2); __cil_print_rule(" ", "allow", r2); } } cil_list_destroy(&matching, CIL_FALSE); cil_list_destroy(&target.perms.classperms, CIL_TRUE); } bounds_destroy_bad(bad); } } exit: return rc; } // assumes policydb is already allocated and initialized properly with things // like policy type set to kernel and version set appropriately int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *policydb) { int rc = SEPOL_ERR; int i; struct cil_args_binary extra_args; policydb_t *pdb = &policydb->p; struct cil_list *neverallows = NULL; hashtab_t filename_trans_table = NULL; hashtab_t range_trans_table = NULL; hashtab_t role_trans_table = NULL; hashtab_t avrulex_ioctl_table = NULL; void **type_value_to_cil = NULL; struct cil_class **class_value_to_cil = NULL; struct cil_perm ***perm_value_to_cil = NULL; if (db == NULL || policydb == NULL) { if (db == NULL) { cil_log(CIL_ERR,"db == NULL\n"); } else if (policydb == NULL) { cil_log(CIL_ERR,"policydb == NULL\n"); } return SEPOL_ERR; } /* libsepol values start at 1. Just allocate extra memory rather than * subtract 1 from the sepol value. */ type_value_to_cil = calloc(db->num_types_and_attrs+1, sizeof(*type_value_to_cil)); if (!type_value_to_cil) goto exit; class_value_to_cil = calloc(db->num_classes+1, sizeof(*class_value_to_cil)); if (!class_value_to_cil) goto exit; perm_value_to_cil = calloc(db->num_classes+1, sizeof(*perm_value_to_cil)); if (!perm_value_to_cil) goto exit; for (i=1; i < db->num_classes+1; i++) { perm_value_to_cil[i] = calloc(PERMS_PER_CLASS+1, sizeof(*perm_value_to_cil[i])); if (!perm_value_to_cil[i]) goto exit; } rc = __cil_policydb_init(pdb, db, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { cil_log(CIL_ERR,"Problem in policydb_init\n"); goto exit; } filename_trans_table = hashtab_create(filename_trans_hash, filename_trans_compare, FILENAME_TRANS_TABLE_SIZE); if (!filename_trans_table) { cil_log(CIL_INFO, "Failure to create hashtab for filename_trans\n"); goto exit; } range_trans_table = hashtab_create(range_trans_hash, range_trans_compare, RANGE_TRANS_TABLE_SIZE); if (!range_trans_table) { cil_log(CIL_INFO, "Failure to create hashtab for range_trans\n"); goto exit; } role_trans_table = hashtab_create(role_trans_hash, role_trans_compare, ROLE_TRANS_TABLE_SIZE); if (!role_trans_table) { cil_log(CIL_INFO, "Failure to create hashtab for role_trans\n"); goto exit; } avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_ioctl_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } cil_list_init(&neverallows, CIL_LIST_ITEM); extra_args.db = db; extra_args.pdb = pdb; extra_args.neverallows = neverallows; extra_args.filename_trans_table = filename_trans_table; extra_args.range_trans_table = range_trans_table; extra_args.role_trans_table = role_trans_table; extra_args.avrulex_ioctl_table = avrulex_ioctl_table; extra_args.type_value_to_cil = type_value_to_cil; for (i = 1; i <= 3; i++) { extra_args.pass = i; rc = cil_tree_walk(db->ast->root, __cil_binary_create_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while walking cil database\n"); goto exit; } if (i == 1) { rc = __cil_policydb_val_arrays_create(pdb); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating val_to_{struct,name} arrays\n"); goto exit; } } if (i == 3) { rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, pdb); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } } } rc = cil_sidorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } rc = __cil_contexts_to_policydb(pdb, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while inserting cil contexts into sepol policydb\n"); goto exit; } if (pdb->type_attr_map == NULL) { rc = __cil_typeattr_bitmap_init(pdb); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while initializing typeattribute bitmap\n"); goto exit; } } cond_optimize_lists(pdb->cond_list); __cil_set_conditional_state_and_flags(pdb); if (db->disable_neverallow != CIL_TRUE) { int violation = CIL_FALSE; cil_log(CIL_INFO, "Checking Neverallows\n"); rc = cil_check_neverallows(db, pdb, neverallows, &violation); if (rc != SEPOL_OK) goto exit; cil_log(CIL_INFO, "Checking User Bounds\n"); rc = bounds_check_users(NULL, pdb); if (rc) { violation = CIL_TRUE; } cil_log(CIL_INFO, "Checking Role Bounds\n"); rc = bounds_check_roles(NULL, pdb); if (rc) { violation = CIL_TRUE; } cil_log(CIL_INFO, "Checking Type Bounds\n"); rc = cil_check_type_bounds(db, pdb, type_value_to_cil, class_value_to_cil, perm_value_to_cil, &violation); if (rc != SEPOL_OK) goto exit; if (violation == CIL_TRUE) { rc = SEPOL_ERR; goto exit; } } /* This pre-expands the roles and users for context validity checking */ if (hashtab_map(pdb->p_roles.table, policydb_role_cache, pdb)) { cil_log(CIL_INFO, "Failure creating roles cache"); rc = SEPOL_ERR; goto exit; } if (hashtab_map(pdb->p_users.table, policydb_user_cache, pdb)) { cil_log(CIL_INFO, "Failure creating users cache"); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: hashtab_destroy(filename_trans_table); hashtab_destroy(range_trans_table); hashtab_destroy(role_trans_table); hashtab_destroy(avrulex_ioctl_table); free(type_value_to_cil); free(class_value_to_cil); /* Range is because libsepol values start at 1. */ for (i=1; i < db->num_classes+1; i++) { free(perm_value_to_cil[i]); } free(perm_value_to_cil); cil_list_destroy(&neverallows, CIL_FALSE); return rc; } libsepol/cil/src/cil_binary.h0100644 0000000 0000000 00000043500 13756670064 015260 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef _CIL_BINARY_H_ #define _CIL_BINARY_H_ #include #include "cil_internal.h" #include "cil_tree.h" #include "cil_list.h" /** * Create a binary policydb from the cil db. * * @param[in] db The cil database. * @param[in] pdb The policy database. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_binary_create(const struct cil_db *db, sepol_policydb_t **pdb); /** * Create a pre allocated binary policydb from the cil db. * * It is assumed that pdb has been allocated and initialzed so that fields such * as policy type and version are set appropriately. It is reccomended that * instead of calling this, one instead calls cil_binary_create, which will * properly allocate and initialize the pdb and then calls this function. This * funcion is used to maintain binary backwards compatability. * * @param[in] db The cil database. * @param[in] pdb The policy database. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *pdb); /** * Insert cil common structure into sepol policydb. * * @param[in] pdb The policy database to insert the common into. * @param[in] datum The cil_common datum. * @param[out] common_out The sepol common to send back. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common_datum_t **common_out); /** * Insert cil class structure into sepol policydb. * * @param[in] pdb The policy database to insert the class into. * @param[in] datum The cil_class datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_class_to_policydb(policydb_t *pdb, struct cil_class *cil_class); /** * Insert cil role structure into sepol policydb. * * @param[in] pdb The policy database to insert the role into. * @param[in] datum The cil_role datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_role_to_policydb(policydb_t *pdb, struct cil_role *cil_role); /** * Insert cil roletype structure into sepol policydb. * * @param[in] pdb The policy database to insert the roletype into. * @param[in] db The cil database * @param[in] datum The cil_roletype datum. * * @return SEPOL_OK upon success or SEPOL_ERR otherwise. */ int cil_roletype_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_role *role); /** * Insert cil type structure into sepol policydb. * * @param[in] pdb The policy database to insert the type into. * @param[in] datum The cil_type datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type, void *type_value_to_cil[]); /** * Insert cil typealias structure into sepol policydb. * * @param[in] pdb The policy database to insert the typealias into. * @param[in] datum The cil_typealias datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typealias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias); /** * Insert cil typepermissive structure into sepol policydb. * The function looks up the perviously inserted type and flips the bit * in the permssive types bitmap that corresponds to that type's value. * * @param[in] pdb The policy database to insert the typepermissive into. * @param[in] datum The cil_typepermissive datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typepermissive_to_policydb(policydb_t *pdb, struct cil_typepermissive *cil_typeperm); /** * Insert cil attribute structure into sepol policydb. * * @param[in] pdb The policy database to insert the attribute into. * @param[in] datum The cil_attribute datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr, void *type_value_to_cil[]); /** * Insert cil attribute structure into sepol type->attribute bitmap. * The function calls helper functions to loop over the attributes lists * of types and negative types. If either of the lists contain an attribute, * the helper functions will recurse into the attribute and record the * attribute's types and negative types. There is no minimum depth. * * @param[in] pdb The policy database that contains the type->attribute bitmap. * @param[in] db The cil database * @param[in] node The tree node that contains the cil_attribute. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *cdb, struct cil_typeattribute *cil_attr); /** * Insert cil policycap structure into sepol policydb. * * @param[in] pdb The policy database to insert the policycap into. * @param[in] node The tree node that contains the cil_policycap. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_policycap_to_policydb(policydb_t *pdb, struct cil_policycap *cil_polcap); /** * Insert cil user structure into sepol policydb. * * @param[in] pdb THe policy database to insert the user into. * @param[in] node The tree node that contains the cil_user. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user); /** * Insert cil userrole structure into sepol policydb. * * @param[in] pdb The policy database to insert the userrole into. * @param[in] db The cil database * @param[in] datum The cil_user * * @return SEPOL_OK upon success or SEPOL_ERR otherwise. */ int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user); /** * Insert cil bool structure into sepol policydb. * * @param[in] pdb THe policy database to insert the bool into. * @param[in] datum The cil_bool datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_bool_to_policydb(policydb_t *pdb, struct cil_bool *cil_bool); /** * Insert all ordered cil category structures into sepol policydb. * * @param[in] pdb The policy database to insert the categories into. * @param[in] db The cil database that contains the category order list. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_catorder_to_policydb(policydb_t *pdb, const struct cil_db *db); /** * Insert cil category alias structure into sepol policydb. * * @param[in] pdb The policy database to insert the category alias into. * @param[in] datum The cil_catalias datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_catalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias); /** * Insert the cil sensitivityorder into sepol policydb. * * @param[in] pdb The policy database to insert the sensitivityorder into. * @param[in] db the cil database that contains the sensitivityorder list. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_sensitivityorder_to_policydb(policydb_t *pdb, const struct cil_db *db); /** * Insert cil type rule structure into sepol policydb. This includes * typetransition, typechange, and typemember. * * @param[in] pdb The policy database to insert the type rule into. * @param[in] datum The cil_type_rule datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_type_rule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_type_rule *cil_rule); /** * Insert cil avrule structure into sepol policydb. * * @param[in] pdb The policy database to insert the avrule into. * @param[in] datum The cil_avrule datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule); /** * Insert cil booleanif structure into sepol policydb. This populates the * policydb conditional list. Each conditional node contains an expression * and true/false avtab_ptr lists that point into te_cond_avtab. * * @param[in] pdb The policy database to insert the booleanif into. * @param[in] node The cil_booleanif node. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node, hashtab_t filename_trans_table); /** * Insert cil role transition structure into sepol policydb. * * @param[in] pdb The policy database to insert the role transition into. * @param[in] datum The cil_role_trans datum. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roletransition *roletrans, hashtab_t role_trans_table); /** * Insert cil role allow structure into sepol policydb. * * @param[in] pdb The policy database to insert the role allow into. * @param[in] datum The cil_role_allow datum. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_roleallow_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roleallow *roleallow); /** * Insert cil file transition structure into sepol policydb. * * @param[in] pdb The policy database to insert the file transition into. * @param[in] datum The cil_nametypetransition datum. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_typetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_nametypetransition *typetrans, hashtab_t filename_trans_table); /** * Insert cil constrain/mlsconstrain structure(s) into sepol policydb. * * @param[in] pdb The policy database to insert the (mls)constrain into. * @param[in] datum The cil_(mls)constrain datum. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_constrain_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_constrain *cil_constrain); /** * Define sepol level. * Associates the sepol level (sensitivity) with categories. * Looks at the cil_sens structure for a list of cil_cats to * associate the sensitivity with. * Sets the sepol level as defined in the sepol policy database. * * @param[in] pdb The policy database that holds the sepol level. * @param[in] datum The cil_sens datum. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_sepol_level_define(policydb_t *pdb, struct cil_sens *cil_sens); /** * Insert cil rangetransition structure into sepol policydb. * * @param[in] pdb The policy database to insert the rangetransition into. * @param[in] datum The cil_rangetransition datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_rangetransition *rangetrans, hashtab_t range_trans_table); /** * Insert cil ibpkeycon structure into sepol policydb. * The function is given a structure containing the sorted ibpkeycons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the ibpkeycon into. * @param[in] node The cil_sort structure that contains the sorted ibpkeycons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons); /** * Insert cil idbev structure into sepol policydb. * The function is given a structure containing the sorted ibendportcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pkeycon into. * @param[in] node The cil_sort structure that contains the sorted ibendportcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *pkeycons); /** * Insert cil portcon structure into sepol policydb. * The function is given a structure containing the sorted portcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the portcon into. * @param[in] node The cil_sort structure that contains the sorted portcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons); /** * Insert cil netifcon structure into sepol policydb. * The function is given a structure containing the sorted netifcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the netifcon into. * @param[in] node The cil_sort structure that contains the sorted netifcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_netifcon_to_policydb(policydb_t *pdb, struct cil_sort *netifcons); /** * Insert cil nodecon structure into sepol policydb. * The function is given a structure containing the sorted nodecons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the nodecon into. * @param[in] node The cil_sort structure that contains the sorted nodecons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons); /** * Insert cil fsuse structure into sepol policydb. * The function is given a structure containing the sorted fsuses and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the fsuse into. * @param[in] node The cil_sort structure that contains the sorted fsuses. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_fsuse_to_policydb(policydb_t *pdb, struct cil_sort *fsuses); /** * Insert cil genfscon structure into sepol policydb. * The function is given a structure containing the sorted genfscons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the genfscon into. * @param[in] node The cil_sort structure that contains the sorted genfscons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons); /** * Insert cil pirqcon structure into sepol policydb. * The function is given a structure containing the sorted pirqcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pirqcon into. * @param[in] node The cil_sort structure that contains the sorted pirqcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_pirqcon_to_policydb(policydb_t *pdb, struct cil_sort *pirqcons); /** * Insert cil iomemcon structure into sepol policydb. * The function is given a structure containing the sorted iomemcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the iomemcon into. * @param[in] node The cil_sort structure that contains the sorted iomemcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_iomemcon_to_policydb(policydb_t *pdb, struct cil_sort *iomemcons); /** * Insert cil ioportcon structure into sepol policydb. * The function is given a structure containing the sorted ioportcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the ioportcon into. * @param[in] node The cil_sort structure that contains the sorted ioportcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ioportcon_to_policydb(policydb_t *pdb, struct cil_sort *ioportcons); /** * Insert cil pcidevicecon structure into sepol policydb. * The function is given a structure containing the sorted pcidevicecons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pcidevicecon into. * @param[in] node The cil_sort structure that contains the sorted pcidevicecons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_pcidevicecon_to_policydb(policydb_t *pdb, struct cil_sort *pcidevicecons); /** * Create an mls level using a cil level. * The function is given a structure containing the a cil_level and * outputs a created mls_level_t. * * @param[in] pdb The policy database to use to get sepol level from cil_level's sensitivity. * @param[in] cil_level The cil_level that will be used to create an mls_level_t. * @param[out] mls_level The mls_level that is created. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_level_to_mls_level(policydb_t *pdb, struct cil_level *cil_level, mls_level_t *mls_level); #endif //_CIL_BINARY_H_ libsepol/cil/src/cil_build_ast.c0100644 0000000 0000000 00000470647 13756670064 015755 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_parser.h" #include "cil_build_ast.h" #include "cil_copy_ast.h" #include "cil_verify.h" #include "cil_strpool.h" struct cil_args_build { struct cil_tree_node *ast; struct cil_db *db; struct cil_tree_node *macro; struct cil_tree_node *boolif; struct cil_tree_node *tunif; struct cil_tree_node *in; }; int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list) { int rc = SEPOL_ERR; struct cil_tree_node *curr; enum cil_syntax syntax[] = { CIL_SYN_N_STRINGS, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_list_init(list, flavor); for (curr = current; curr != NULL; curr = curr->next) { cil_list_append(*list, CIL_STRING, curr->data); } return SEPOL_OK; exit: return rc; } /* * Determine whether or not multiple declarations of the same key can share a * datum, given the new datum and the one already present in a given symtab. */ int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur, __attribute__((unused)) struct cil_symtab_datum *old, enum cil_flavor f) { int rc = CIL_FALSE; switch (f) { case CIL_TYPE: case CIL_TYPEATTRIBUTE: /* type and typeattribute statements insert empty datums, ret true */ rc = CIL_TRUE; break; default: break; } return rc; } int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) { int rc = SEPOL_ERR; symtab_t *symtab = NULL; struct cil_symtab_datum *prev; rc = __cil_verify_name((const char*)key); if (rc != SEPOL_OK) { goto exit; } rc = cil_get_symtab(ast_node->parent, &symtab, sflavor); if (rc != SEPOL_OK) { goto exit; } ast_node->data = datum; ast_node->flavor = nflavor; if (symtab != NULL) { rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node); if (rc == SEPOL_EEXIST) { if (!db->multiple_decls || cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev) != SEPOL_OK || !cil_is_datum_multiple_decl(datum, prev, nflavor)) { /* multiple_decls not ok, ret error */ cil_log(CIL_ERR, "Re-declaration of %s %s\n", cil_node_to_string(ast_node), key); if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) { if (sflavor == CIL_SYM_BLOCKS) { struct cil_tree_node *node = datum->nodes->head->data; cil_tree_log(node, CIL_ERR, "Previous declaration"); } } goto exit; } /* multiple_decls is enabled and works for this datum type, add node */ cil_list_append(prev->nodes, CIL_NODE, ast_node); ast_node->data = prev; cil_symtab_datum_destroy(datum); free(datum); } } if (ast_node->flavor >= CIL_MIN_DECLARATIVE && ast_node->parent->flavor == CIL_MACRO) { struct cil_list_item *item; struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params; if (param_list != NULL) { cil_list_for_each(item, param_list) { struct cil_param *param = item->data; if (param->flavor == ast_node->flavor) { if (param->str == key) { cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key); rc = SEPOL_ERR; goto exit; } } } } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to create node\n"); return rc; } void cil_clear_node(struct cil_tree_node *ast_node) { if (ast_node == NULL) { return; } ast_node->data = NULL; ast_node->flavor = CIL_NONE; } int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_block *block = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_block_init(&block); block->is_abstract = is_abstract; key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad block declaration"); cil_destroy_block(block); cil_clear_node(ast_node); return rc; } void cil_destroy_block(struct cil_block *block) { if (block == NULL) { return; } cil_symtab_datum_destroy(&block->datum); cil_symtab_array_destroy(block->symtab); cil_list_destroy(&block->bi_nodes, CIL_FALSE); free(block); } int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_blockinherit *inherit = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_blockinherit_init(&inherit); inherit->block_str = parse_current->next->data; ast_node->data = inherit; ast_node->flavor = CIL_BLOCKINHERIT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration"); cil_destroy_blockinherit(inherit); return rc; } void cil_destroy_blockinherit(struct cil_blockinherit *inherit) { if (inherit == NULL) { return; } free(inherit); } int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_blockabstract *abstract = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_blockabstract_init(&abstract); abstract->block_str = parse_current->next->data; ast_node->data = abstract; ast_node->flavor = CIL_BLOCKABSTRACT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration"); cil_destroy_blockabstract(abstract); return rc; } void cil_destroy_blockabstract(struct cil_blockabstract *abstract) { if (abstract == NULL) { return; } free(abstract); } int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_in *in = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_in_init(&in); in->block_str = parse_current->next->data; ast_node->data = in; ast_node->flavor = CIL_IN; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad in statement"); cil_destroy_in(in); return rc; } void cil_destroy_in(struct cil_in *in) { if (in == NULL) { return; } cil_symtab_array_destroy(in->symtab); free(in); } int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *class = NULL; struct cil_tree_node *perms = NULL; int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&class); key = parse_current->next->data; if (key == CIL_KEY_UNORDERED) { cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next != NULL) { perms = parse_current->next->next->cl_head; rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms); if (rc != SEPOL_OK) { goto exit; } if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad class declaration"); cil_destroy_class(class); cil_clear_node(ast_node); return rc; } void cil_destroy_class(struct cil_class *class) { if (class == NULL) { return; } cil_symtab_datum_destroy(&class->datum); cil_symtab_destroy(&class->perms); free(class); } int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_classorder *classorder = NULL; struct cil_list_item *curr = NULL; struct cil_list_item *head = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classorder_init(&classorder); rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASSORDER, &classorder->class_list_str); if (rc != SEPOL_OK) { goto exit; } head = classorder->class_list_str->head; cil_list_for_each(curr, classorder->class_list_str) { if (curr->data == CIL_KEY_UNORDERED) { if (curr == head && curr->next == NULL) { cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n"); rc = SEPOL_ERR; goto exit; } else if (curr != head) { cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n"); rc = SEPOL_ERR; goto exit; } } } ast_node->data = classorder; ast_node->flavor = CIL_CLASSORDER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration"); cil_destroy_classorder(classorder); return rc; } void cil_destroy_classorder(struct cil_classorder *classorder) { if (classorder == NULL) { return; } if (classorder->class_list_str != NULL) { cil_list_destroy(&classorder->class_list_str, 1); } free(classorder); } int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) { char *key = NULL; struct cil_perm *perm = NULL; int rc = SEPOL_ERR; cil_perm_init(&perm); key = parse_current->data; if (key == NULL) { cil_log(CIL_ERR, "Bad permission\n"); goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor); if (rc != SEPOL_OK) { goto exit; } perm->value = *num_perms; (*num_perms)++; return SEPOL_OK; exit: cil_destroy_perm(perm); cil_clear_node(ast_node); return rc; } void cil_destroy_perm(struct cil_perm *perm) { if (perm == NULL) { return; } cil_symtab_datum_destroy(&perm->datum); cil_list_destroy(&perm->classperms, CIL_FALSE); free(perm); } int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) { int rc = SEPOL_ERR; struct cil_tree_node *new_ast = NULL; while(current_perm != NULL) { if (current_perm->cl_head != NULL) { rc = SEPOL_ERR; goto exit; } cil_tree_node_init(&new_ast); new_ast->parent = ast_node; new_ast->line = current_perm->line; new_ast->hll_line = current_perm->hll_line; rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); if (rc != SEPOL_OK) { cil_tree_node_destroy(&new_ast); goto exit; } if (ast_node->cl_head == NULL) { ast_node->cl_head = new_ast; } else { ast_node->cl_tail->next = new_ast; } ast_node->cl_tail = new_ast; current_perm = current_perm->next; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad permissions\n"); cil_tree_children_destroy(ast_node); cil_clear_node(ast_node); return rc; } int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_expr(start_perm, CIL_PERM, perms); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad permission list or expression\n"); return rc; } int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classperms_init(cp); (*cp)->class_str = parse_current->data; rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs); if (rc != SEPOL_OK) { cil_destroy_classperms(*cp); goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad class-permissions\n"); *cp = NULL; return rc; } void cil_destroy_classperms(struct cil_classperms *cp) { if (cp == NULL) { return; } cil_list_destroy(&cp->perm_strs, CIL_TRUE); cil_list_destroy(&cp->perms, CIL_FALSE); free(cp); } void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set) { cil_classperms_set_init(cp_set); (*cp_set)->set_str = parse_current->data; } void cil_destroy_classperms_set(struct cil_classperms_set *cp_set) { if (cp_set == NULL) { return; } free(cp_set); } int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list) { int rc = SEPOL_ERR; struct cil_tree_node *curr; enum cil_syntax syntax[] = { CIL_SYN_STRING | CIL_SYN_LIST, }; int syntax_len = sizeof(syntax)/sizeof(*syntax); if (parse_current == NULL || cp_list == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_list_init(cp_list, CIL_CLASSPERMS); curr = parse_current->cl_head; if (curr == NULL) { /* Class-perms form: SET1 */ struct cil_classperms_set *new_cp_set; cil_fill_classperms_set(parse_current, &new_cp_set); cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set); } else if (curr->cl_head == NULL) { /* Class-perms form: (CLASS1 (PERM1 ...)) */ struct cil_classperms *new_cp; rc = cil_fill_classperms(curr, &new_cp); if (rc != SEPOL_OK) { goto exit; } cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp); } else { cil_log(CIL_ERR, "Bad class-permissions list syntax\n"); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Problem filling class-permissions list\n"); cil_list_destroy(cp_list, CIL_TRUE); return rc; } void cil_destroy_classperms_list(struct cil_list **cp_list) { struct cil_list_item *curr; if (cp_list == NULL || *cp_list == NULL) { return; } cil_list_for_each(curr, *cp_list) { if (curr->flavor == CIL_CLASSPERMS) { cil_destroy_classperms(curr->data); } else { cil_destroy_classperms_set(curr->data); } } cil_list_destroy(cp_list, CIL_FALSE); } int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; char *key = NULL; struct cil_classpermission *cp = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classpermission_init(&cp); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration"); cil_destroy_classpermission(cp); cil_clear_node(ast_node); return rc; } void cil_destroy_classpermission(struct cil_classpermission *cp) { if (cp == NULL) { return; } if (cp->datum.name != NULL) { cil_list_destroy(&cp->classperms, CIL_FALSE); } else { /* anonymous classpermission from call */ cil_destroy_classperms_list(&cp->classperms); } cil_symtab_datum_destroy(&cp->datum); free(cp); } int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_classpermissionset *cps = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classpermissionset_init(&cps); cps->set_str = parse_current->next->data; rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = cps; ast_node->flavor = CIL_CLASSPERMISSIONSET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset"); cil_destroy_classpermissionset(cps); return rc; } void cil_destroy_classpermissionset(struct cil_classpermissionset *cps) { if (cps == NULL) { return; } cil_destroy_classperms_list(&cps->classperms); free(cps); } int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *map = NULL; int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&map); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration"); cil_destroy_class(map); cil_clear_node(ast_node); return rc; } int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_classmapping *mapping = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classmapping_init(&mapping); mapping->map_class_str = parse_current->next->data; mapping->map_perm_str = parse_current->next->next->data; rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = mapping; ast_node->flavor = CIL_CLASSMAPPING; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration"); cil_destroy_classmapping(mapping); return rc; } void cil_destroy_classmapping(struct cil_classmapping *mapping) { if (mapping == NULL) { return; } cil_destroy_classperms_list(&mapping->classperms); free(mapping); } // TODO try to merge some of this with cil_gen_class (helper function for both) int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *common = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&common); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms); if (rc != SEPOL_OK) { goto exit; } if (common->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad common declaration"); cil_destroy_class(common); cil_clear_node(ast_node); return rc; } int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_classcommon *clscom = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classcommon_init(&clscom); clscom->class_str = parse_current->next->data; clscom->common_str = parse_current->next->next->data; ast_node->data = clscom; ast_node->flavor = CIL_CLASSCOMMON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration"); cil_destroy_classcommon(clscom); return rc; } void cil_destroy_classcommon(struct cil_classcommon *clscom) { if (clscom == NULL) { return; } free(clscom); } int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sid *sid = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sid_init(&sid); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration"); cil_destroy_sid(sid); cil_clear_node(ast_node); return rc; } void cil_destroy_sid(struct cil_sid *sid) { if (sid == NULL) { return; } cil_symtab_datum_destroy(&sid->datum); free(sid); } int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sidcontext *sidcon = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sidcontext_init(&sidcon); sidcon->sid_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { sidcon->context_str = parse_current->next->next->data; } else { cil_context_init(&sidcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = sidcon; ast_node->flavor = CIL_SIDCONTEXT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration"); cil_destroy_sidcontext(sidcon); return rc; } void cil_destroy_sidcontext(struct cil_sidcontext *sidcon) { if (sidcon == NULL) { return; } if (sidcon->context_str == NULL && sidcon->context != NULL) { cil_destroy_context(sidcon->context); } free(sidcon); } int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sidorder *sidorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sidorder_init(&sidorder); rc = cil_fill_list(parse_current->next->cl_head, CIL_SIDORDER, &sidorder->sid_list_str); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(curr, sidorder->sid_list_str) { if (curr->data == CIL_KEY_UNORDERED) { cil_log(CIL_ERR, "Sidorder cannot be unordered.\n"); rc = SEPOL_ERR; goto exit; } } ast_node->data = sidorder; ast_node->flavor = CIL_SIDORDER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration"); cil_destroy_sidorder(sidorder); return rc; } void cil_destroy_sidorder(struct cil_sidorder *sidorder) { if (sidorder == NULL) { return; } if (sidorder->sid_list_str != NULL) { cil_list_destroy(&sidorder->sid_list_str, 1); } free(sidorder); } int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_user *user = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_user_init(&user); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad user declaration"); cil_destroy_user(user); cil_clear_node(ast_node); return rc; } void cil_destroy_user(struct cil_user *user) { if (user == NULL) { return; } cil_symtab_datum_destroy(&user->datum); ebitmap_destroy(user->roles); free(user->roles); free(user); } int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_userattribute *attr = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration"); cil_destroy_userattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_userattribute(struct cil_userattribute *attr) { struct cil_list_item *expr = NULL; struct cil_list_item *next = NULL; if (attr == NULL) { return; } if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ expr = attr->expr_list->head; while (expr != NULL) { next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } cil_symtab_datum_destroy(&attr->datum); ebitmap_destroy(attr->users); free(attr->users); free(attr); } int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_USERATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration"); cil_destroy_userattributeset(attrset); return rc; } void cil_destroy_userattributeset(struct cil_userattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userlevel *usrlvl = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userlevel_init(&usrlvl); usrlvl->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { usrlvl->level_str = parse_current->next->next->data; } else { cil_level_init(&usrlvl->level); rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = usrlvl; ast_node->flavor = CIL_USERLEVEL; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration"); cil_destroy_userlevel(usrlvl); return rc; } void cil_destroy_userlevel(struct cil_userlevel *usrlvl) { if (usrlvl == NULL) { return; } if (usrlvl->level_str == NULL && usrlvl->level != NULL) { cil_destroy_level(usrlvl->level); } free(usrlvl); } int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrange *userrange = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userrange_init(&userrange); userrange->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { userrange->range_str = parse_current->next->next->data; } else { cil_levelrange_init(&userrange->range); rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = userrange; ast_node->flavor = CIL_USERRANGE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration"); cil_destroy_userrange(userrange); return rc; } void cil_destroy_userrange(struct cil_userrange *userrange) { if (userrange == NULL) { return; } if (userrange->range_str == NULL && userrange->range != NULL) { cil_destroy_levelrange(userrange->range); } free(userrange); } int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userprefix *userprefix = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userprefix_init(&userprefix); userprefix->user_str = parse_current->next->data; userprefix->prefix_str = parse_current->next->next->data; ast_node->data = userprefix; ast_node->flavor = CIL_USERPREFIX; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration"); cil_destroy_userprefix(userprefix); return rc; } void cil_destroy_userprefix(struct cil_userprefix *userprefix) { if (userprefix == NULL) { return; } free(userprefix); } int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_selinuxuser_init(&selinuxuser); selinuxuser->name_str = parse_current->next->data; selinuxuser->user_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { selinuxuser->range_str = parse_current->next->next->next->data; } else { cil_levelrange_init(&selinuxuser->range); rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = selinuxuser; ast_node->flavor = CIL_SELINUXUSER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration"); cil_destroy_selinuxuser(selinuxuser); return rc; } int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_selinuxuser_init(&selinuxuser); selinuxuser->name_str = cil_strpool_add("__default__"); selinuxuser->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { selinuxuser->range_str = parse_current->next->next->data; } else { cil_levelrange_init(&selinuxuser->range); rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = selinuxuser; ast_node->flavor = CIL_SELINUXUSERDEFAULT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration"); cil_destroy_selinuxuser(selinuxuser); return rc; } void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser) { if (selinuxuser == NULL) { return; } if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) { cil_destroy_levelrange(selinuxuser->range); } free(selinuxuser); } int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_role *role = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_role_init(&role); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad role declaration"); cil_destroy_role(role); cil_clear_node(ast_node); return rc; } void cil_destroy_role(struct cil_role *role) { if (role == NULL) { return; } cil_symtab_datum_destroy(&role->datum); ebitmap_destroy(role->types); free(role->types); free(role); } int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletype *roletype = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roletype_init(&roletype); roletype->role_str = parse_current->next->data; roletype->type_str = parse_current->next->next->data; ast_node->data = roletype; ast_node->flavor = CIL_ROLETYPE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration"); cil_destroy_roletype(roletype); return rc; } void cil_destroy_roletype(struct cil_roletype *roletype) { if (roletype == NULL) { return; } free(roletype); } int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrole *userrole = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userrole_init(&userrole); userrole->user_str = parse_current->next->data; userrole->role_str = parse_current->next->next->data; ast_node->data = userrole; ast_node->flavor = CIL_USERROLE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration"); cil_destroy_userrole(userrole); return rc; } void cil_destroy_userrole(struct cil_userrole *userrole) { if (userrole == NULL) { return; } free(userrole); } int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletransition *roletrans = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roletransition_init(&roletrans); roletrans->src_str = parse_current->next->data; roletrans->tgt_str = parse_current->next->next->data; roletrans->obj_str = parse_current->next->next->next->data; roletrans->result_str = parse_current->next->next->next->next->data; ast_node->data = roletrans; ast_node->flavor = CIL_ROLETRANSITION; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule"); cil_destroy_roletransition(roletrans); return rc; } void cil_destroy_roletransition(struct cil_roletransition *roletrans) { if (roletrans == NULL) { return; } free(roletrans); } int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleallow *roleallow = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roleallow_init(&roleallow); roleallow->src_str = parse_current->next->data; roleallow->tgt_str = parse_current->next->next->data; ast_node->data = roleallow; ast_node->flavor = CIL_ROLEALLOW; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule"); cil_destroy_roleallow(roleallow); return rc; } void cil_destroy_roleallow(struct cil_roleallow *roleallow) { if (roleallow == NULL) { return; } free(roleallow); } int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_roleattribute *attr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->data == CIL_KEY_SELF) { cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); rc = SEPOL_ERR; goto exit; } cil_roleattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration"); cil_destroy_roleattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_roleattribute(struct cil_roleattribute *attr) { if (attr == NULL) { return; } if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } cil_symtab_datum_destroy(&attr->datum); ebitmap_destroy(attr->roles); free(attr->roles); free(attr); } int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roleattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_ROLEATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration"); cil_destroy_roleattributeset(attrset); return rc; } void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_avrule_init(&rule); rule->is_extended = 0; rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = rule; ast_node->flavor = CIL_AVRULE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad allow rule"); cil_destroy_avrule(rule); return rc; } void cil_destroy_avrule(struct cil_avrule *rule) { if (rule == NULL) { return; } if (!rule->is_extended) { cil_destroy_classperms_list(&rule->perms.classperms); } else { if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) { cil_destroy_permissionx(rule->perms.x.permx); } } free(rule); } int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (parse_current->data == CIL_KEY_IOCTL) { permx->kind = CIL_PERMX_KIND_IOCTL; } else { cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data); rc = SEPOL_ERR; goto exit; } permx->obj_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content"); return rc; } int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_permissionx *permx = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_permissionx_init(&permx); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement"); cil_destroy_permissionx(permx); cil_clear_node(ast_node); return rc; } void cil_destroy_permissionx(struct cil_permissionx *permx) { if (permx == NULL) { return; } cil_symtab_datum_destroy(&permx->datum); cil_list_destroy(&permx->expr_str, CIL_TRUE); ebitmap_destroy(permx->perms); free(permx->perms); free(permx); } int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_avrule_init(&rule); rule->is_extended = 1; rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { rule->perms.x.permx_str = parse_current->next->next->next->data; } else { cil_permissionx_init(&rule->perms.x.permx); rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = rule; ast_node->flavor = CIL_AVRULEX; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule"); cil_destroy_avrule(rule); return rc; } int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_type_rule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_type_rule_init(&rule); rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; rule->obj_str = parse_current->next->next->next->data; rule->result_str = parse_current->next->next->next->next->data; ast_node->data = rule; ast_node->flavor = CIL_TYPE_RULE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad type rule"); cil_destroy_type_rule(rule); return rc; } void cil_destroy_type_rule(struct cil_type_rule *rule) { if (rule == NULL) { return; } free(rule); } int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_type *type = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->data == CIL_KEY_SELF) { cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); rc = SEPOL_ERR; goto exit; } cil_type_init(&type); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad type declaration"); cil_destroy_type(type); cil_clear_node(ast_node); return rc; } void cil_destroy_type(struct cil_type *type) { if (type == NULL) { return; } cil_symtab_datum_destroy(&type->datum); free(type); } int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_typeattribute *attr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->data == CIL_KEY_SELF) { cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); rc = SEPOL_ERR; goto exit; } cil_typeattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration"); cil_destroy_typeattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_typeattribute(struct cil_typeattribute *attr) { if (attr == NULL) { return; } cil_symtab_datum_destroy(&attr->datum); if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } ebitmap_destroy(attr->types); free(attr->types); free(attr); } int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_bool *boolean = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_bool_init(&boolean); key = parse_current->next->data; if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { boolean->value = CIL_TRUE; } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { boolean->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: if (tunableif) { cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration"); } else { cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration"); } cil_destroy_bool(boolean); cil_clear_node(ast_node); return rc; } void cil_destroy_bool(struct cil_bool *boolean) { if (boolean == NULL) { return; } cil_symtab_datum_destroy(&boolean->datum); free(boolean); } int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_tunable *tunable = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_tunable_init(&tunable); key = parse_current->next->data; if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { tunable->value = CIL_TRUE; } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { tunable->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration"); cil_destroy_tunable(tunable); cil_clear_node(ast_node); return rc; } void cil_destroy_tunable(struct cil_tunable *tunable) { if (tunable == NULL) { return; } cil_symtab_datum_destroy(&tunable->datum); free(tunable); } static enum cil_flavor __cil_get_expr_operator_flavor(const char *op) { if (op == NULL) return CIL_NONE; else if (op == CIL_KEY_AND) return CIL_AND; else if (op == CIL_KEY_OR) return CIL_OR; else if (op == CIL_KEY_NOT) return CIL_NOT; else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */ else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */ else if (op == CIL_KEY_XOR) return CIL_XOR; else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */ else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */ else return CIL_NONE; } static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth); static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) { int rc = SEPOL_ERR; enum cil_flavor op; if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) { cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH); goto exit; } op = __cil_get_expr_operator_flavor(current->data); rc = cil_verify_expr_syntax(current, op, flavor); if (rc != SEPOL_OK) { goto exit; } if (op != CIL_NONE) { cil_list_append(expr, CIL_OP, (void *)op); current = current->next; } if (op == CIL_NONE || op == CIL_ALL) { (*depth)++; } for (;current != NULL; current = current->next) { rc = __cil_fill_expr(current, flavor, expr, depth); if (rc != SEPOL_OK) { goto exit; } } (*depth)--; return SEPOL_OK; exit: return rc; } static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) { int rc = SEPOL_ERR; if (current->cl_head == NULL) { enum cil_flavor op = __cil_get_expr_operator_flavor(current->data); if (op != CIL_NONE) { cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data); goto exit; } cil_list_append(expr, CIL_STRING, current->data); } else { struct cil_list *sub_expr; cil_list_init(&sub_expr, flavor); rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth); if (rc != SEPOL_OK) { cil_list_destroy(&sub_expr, CIL_TRUE); goto exit; } cil_list_append(expr, CIL_LIST, sub_expr); } return SEPOL_OK; exit: return rc; } int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) { int rc = SEPOL_ERR; int depth = 0; cil_list_init(expr, flavor); if (current->cl_head == NULL) { rc = __cil_fill_expr(current, flavor, *expr, &depth); } else { rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth); } if (rc != SEPOL_OK) { cil_list_destroy(expr, CIL_TRUE); cil_log(CIL_ERR, "Bad expression\n"); } return rc; } static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op) { if (op == CIL_KEY_AND) return CIL_AND; else if (op == CIL_KEY_OR) return CIL_OR; else if (op == CIL_KEY_NOT) return CIL_NOT; else if (op == CIL_KEY_EQ) return CIL_EQ; else if (op == CIL_KEY_NEQ) return CIL_NEQ; else if (op == CIL_KEY_CONS_DOM) return CIL_CONS_DOM; else if (op == CIL_KEY_CONS_DOMBY) return CIL_CONS_DOMBY; else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP; else return CIL_NONE; } static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand) { if (operand == NULL) return CIL_LIST; else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1; else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2; else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3; else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1; else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2; else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3; else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1; else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2; else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3; else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1; else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2; else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1; else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2; else return CIL_STRING; } static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum cil_flavor expr_flavor, enum cil_flavor op, struct cil_list **leaf_expr) { int rc = SEPOL_ERR; enum cil_flavor leaf_expr_flavor = CIL_NONE; enum cil_flavor l_flavor = CIL_NONE; enum cil_flavor r_flavor = CIL_NONE; l_flavor = __cil_get_constraint_operand_flavor(current->next->data); r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data); switch (l_flavor) { case CIL_CONS_U1: case CIL_CONS_U2: case CIL_CONS_U3: leaf_expr_flavor = CIL_USER; break; case CIL_CONS_R1: case CIL_CONS_R2: case CIL_CONS_R3: leaf_expr_flavor = CIL_ROLE; break; case CIL_CONS_T1: case CIL_CONS_T2: case CIL_CONS_T3: leaf_expr_flavor = CIL_TYPE; break; case CIL_CONS_L1: case CIL_CONS_L2: case CIL_CONS_H1: case CIL_CONS_H2: leaf_expr_flavor = CIL_LEVEL; break; default: cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data); goto exit; } rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor); if (rc != SEPOL_OK) { goto exit; } cil_list_init(leaf_expr, leaf_expr_flavor); cil_list_append(*leaf_expr, CIL_OP, (void *)op); cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor); if (r_flavor == CIL_STRING) { cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data); } else if (r_flavor == CIL_LIST) { struct cil_list *sub_list; cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list); cil_list_append(*leaf_expr, CIL_LIST, &sub_list); } else { cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor); } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr, int *depth) { int rc = SEPOL_ERR; enum cil_flavor op; struct cil_list *lexpr; struct cil_list *rexpr; if (current->data == NULL || current->cl_head != NULL) { cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n"); goto exit; } if (*depth > CEXPR_MAXDEPTH) { cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH); rc = SEPOL_ERR; goto exit; } op = __cil_get_constraint_operator_flavor(current->data); rc = cil_verify_constraint_expr_syntax(current, op); if (rc != SEPOL_OK) { goto exit; } switch (op) { case CIL_EQ: case CIL_NEQ: case CIL_CONS_DOM: case CIL_CONS_DOMBY: case CIL_CONS_INCOMP: (*depth)++; rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr); if (rc != SEPOL_OK) { goto exit; } break; case CIL_NOT: rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); if (rc != SEPOL_OK) { goto exit; } cil_list_init(expr, flavor); cil_list_append(*expr, CIL_OP, (void *)op); cil_list_append(*expr, CIL_LIST, lexpr); break; default: rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); if (rc != SEPOL_OK) { goto exit; } rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth); if (rc != SEPOL_OK) { cil_list_destroy(&lexpr, CIL_TRUE); goto exit; } cil_list_init(expr, flavor); cil_list_append(*expr, CIL_OP, (void *)op); cil_list_append(*expr, CIL_LIST, lexpr); cil_list_append(*expr, CIL_LIST, rexpr); break; } (*depth)--; return SEPOL_OK; exit: return rc; } int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) { int rc = SEPOL_ERR; int depth = 0; if (current->cl_head == NULL) { goto exit; } rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad expression tree for constraint\n"); return rc; } int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_booleanif *bif = NULL; struct cil_tree_node *next = NULL; struct cil_tree_node *cond = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_boolif_init(&bif); bif->preserved_tunable = tunableif; rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr); if (rc != SEPOL_OK) { goto exit; } cond = parse_current->next->next; /* Destroying expr tree after stack is created*/ if (cond->cl_head->data != CIL_KEY_CONDTRUE && cond->cl_head->data != CIL_KEY_CONDFALSE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional neither true nor false\n"); goto exit; } if (cond->next != NULL) { cond = cond->next; if (cond->cl_head->data != CIL_KEY_CONDTRUE && cond->cl_head->data != CIL_KEY_CONDFALSE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional neither true nor false\n"); goto exit; } } next = parse_current->next->next; cil_tree_subtree_destroy(parse_current->next); parse_current->next = next; ast_node->flavor = CIL_BOOLEANIF; ast_node->data = bif; return SEPOL_OK; exit: if (tunableif) { cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration"); } else { cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration"); } cil_destroy_boolif(bif); return rc; } void cil_destroy_boolif(struct cil_booleanif *bif) { if (bif == NULL) { return; } cil_list_destroy(&bif->str_expr, CIL_TRUE); cil_list_destroy(&bif->datum_expr, CIL_FALSE); free(bif); } int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_tunableif *tif = NULL; struct cil_tree_node *next = NULL; struct cil_tree_node *cond = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_tunif_init(&tif); rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr); if (rc != SEPOL_OK) { goto exit; } cond = parse_current->next->next; if (cond->cl_head->data != CIL_KEY_CONDTRUE && cond->cl_head->data != CIL_KEY_CONDFALSE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional neither true nor false\n"); goto exit; } if (cond->next != NULL) { cond = cond->next; if (cond->cl_head->data != CIL_KEY_CONDTRUE && cond->cl_head->data != CIL_KEY_CONDFALSE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional neither true nor false\n"); goto exit; } } /* Destroying expr tree after stack is created*/ next = parse_current->next->next; cil_tree_subtree_destroy(parse_current->next); parse_current->next = next; ast_node->flavor = CIL_TUNABLEIF; ast_node->data = tif; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration"); cil_destroy_tunif(tif); return rc; } void cil_destroy_tunif(struct cil_tunableif *tif) { if (tif == NULL) { return; } cil_list_destroy(&tif->str_expr, CIL_TRUE); cil_list_destroy(&tif->datum_expr, CIL_FALSE); free(tif); } int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_N_LISTS, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_condblock *cb = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n"); goto exit; } ast_node->flavor = CIL_CONDBLOCK; cil_condblock_init(&cb); cb->flavor = flavor; ast_node->data = cb; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration", (char*)parse_current->data); cil_destroy_condblock(cb); return rc; } void cil_destroy_condblock(struct cil_condblock *cb) { if (cb == NULL) { return; } cil_symtab_array_destroy(cb->symtab); free(cb); } int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_alias *alias = NULL; enum cil_sym_index sym_index; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) { cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); rc = SEPOL_ERR; goto exit; } cil_alias_init(&alias); key = parse_current->next->data; rc = cil_flavor_to_symtab_index(flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data); cil_destroy_alias(alias); cil_clear_node(ast_node); return rc; } void cil_destroy_alias(struct cil_alias *alias) { if (alias == NULL) { return; } cil_symtab_datum_destroy(&alias->datum); alias->actual = NULL; free(alias); } int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_aliasactual *aliasactual = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) { cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); rc = SEPOL_ERR; goto exit; } cil_aliasactual_init(&aliasactual); aliasactual->alias_str = parse_current->next->data; aliasactual->actual_str = parse_current->next->next->data; ast_node->data = aliasactual; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current)); cil_clear_node(ast_node); return rc; } void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual) { if (aliasactual == NULL) { return; } free(aliasactual); } int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typeattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_typeattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_TYPEATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement"); cil_destroy_typeattributeset(attrset); return rc; } void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_END }; char *expand_str; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_expandtypeattribute *expandattr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_expandtypeattribute_init(&expandattr); if (parse_current->next->cl_head == NULL) { cil_list_init(&expandattr->attr_strs, CIL_TYPE); cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs); if (rc != SEPOL_OK) { goto exit; } } expand_str = parse_current->next->next->data; if (expand_str == CIL_KEY_CONDTRUE) { expandattr->expand = CIL_TRUE; } else if (expand_str == CIL_KEY_CONDFALSE) { expandattr->expand = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); goto exit; } ast_node->data = expandattr; ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement"); cil_destroy_expandtypeattribute(expandattr); return rc; } void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr) { if (expandattr == NULL) { return; } cil_list_destroy(&expandattr->attr_strs, CIL_TRUE); cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); free(expandattr); } int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typepermissive *typeperm = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_typepermissive_init(&typeperm); typeperm->type_str = parse_current->next->data; ast_node->data = typeperm; ast_node->flavor = CIL_TYPEPERMISSIVE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration"); cil_destroy_typepermissive(typeperm); return rc; } void cil_destroy_typepermissive(struct cil_typepermissive *typeperm) { if (typeperm == NULL) { return; } free(typeperm); } int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *s1, *s2, *s3, *s4, *s5; if (db == NULL || parse_current == NULL || ast_node == NULL ) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } s1 = parse_current->next->data; s2 = parse_current->next->next->data; s3 = parse_current->next->next->next->data; s4 = parse_current->next->next->next->next->data; s5 = NULL; if (parse_current->next->next->next->next->next) { if (s4 == CIL_KEY_STAR) { s4 = parse_current->next->next->next->next->next->data; } else { s5 = parse_current->next->next->next->next->next->data; } } if (s5) { struct cil_nametypetransition *nametypetrans = NULL; cil_nametypetransition_init(&nametypetrans); nametypetrans->src_str = s1; nametypetrans->tgt_str = s2; nametypetrans->obj_str = s3; nametypetrans->result_str = s5; nametypetrans->name_str = s4; ast_node->data = nametypetrans; ast_node->flavor = CIL_NAMETYPETRANSITION; } else { struct cil_type_rule *rule = NULL; cil_type_rule_init(&rule); rule->rule_kind = CIL_TYPE_TRANSITION; rule->src_str = s1; rule->tgt_str = s2; rule->obj_str = s3; rule->result_str = s4; ast_node->data = rule; ast_node->flavor = CIL_TYPE_RULE; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration"); return rc; } void cil_destroy_name(struct cil_name *name) { if (name == NULL) { return; } cil_symtab_datum_destroy(&name->datum); free(name); } void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans) { if (nametypetrans == NULL) { return; } free(nametypetrans); } int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_rangetransition *rangetrans = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL ) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_rangetransition_init(&rangetrans); rangetrans->src_str = parse_current->next->data; rangetrans->exec_str = parse_current->next->next->data; rangetrans->obj_str = parse_current->next->next->next->data; rangetrans->range_str = NULL; if (parse_current->next->next->next->next->cl_head == NULL) { rangetrans->range_str = parse_current->next->next->next->next->data; } else { cil_levelrange_init(&rangetrans->range); rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = rangetrans; ast_node->flavor = CIL_RANGETRANSITION; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration"); cil_destroy_rangetransition(rangetrans); return rc; } void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans == NULL) { return; } if (rangetrans->range_str == NULL && rangetrans->range != NULL) { cil_destroy_levelrange(rangetrans->range); } free(rangetrans); } int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sens *sens = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sens_init(&sens); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration"); cil_destroy_sensitivity(sens); cil_clear_node(ast_node); return rc; } void cil_destroy_sensitivity(struct cil_sens *sens) { if (sens == NULL) { return; } cil_symtab_datum_destroy(&sens->datum); cil_list_destroy(&sens->cats_list, CIL_FALSE); free(sens); } int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_cat *cat = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_cat_init(&cat); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad category declaration"); cil_destroy_category(cat); cil_clear_node(ast_node); return rc; } void cil_destroy_category(struct cil_cat *cat) { if (cat == NULL) { return; } cil_symtab_datum_destroy(&cat->datum); free(cat); } int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_catset *catset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_catset_init(&catset); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_cats(parse_current->next->next, &catset->cats); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration"); cil_destroy_catset(catset); cil_clear_node(ast_node); return rc; } void cil_destroy_catset(struct cil_catset *catset) { if (catset == NULL) { return; } cil_symtab_datum_destroy(&catset->datum); cil_destroy_cats(catset->cats); free(catset); } int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_catorder *catorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_catorder_init(&catorder); rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(curr, catorder->cat_list_str) { if (curr->data == CIL_KEY_UNORDERED) { cil_log(CIL_ERR, "Category order cannot be unordered.\n"); rc = SEPOL_ERR; goto exit; } } ast_node->data = catorder; ast_node->flavor = CIL_CATORDER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration"); cil_destroy_catorder(catorder); return rc; } void cil_destroy_catorder(struct cil_catorder *catorder) { if (catorder == NULL) { return; } if (catorder->cat_list_str != NULL) { cil_list_destroy(&catorder->cat_list_str, 1); } free(catorder); } int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sensorder *sensorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sensorder_init(&sensorder); rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(curr, sensorder->sens_list_str) { if (curr->data == CIL_KEY_UNORDERED) { cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n"); rc = SEPOL_ERR; goto exit; } } ast_node->data = sensorder; ast_node->flavor = CIL_SENSITIVITYORDER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration"); cil_destroy_sensitivityorder(sensorder); return rc; } void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder) { if (sensorder == NULL) { return; } if (sensorder->sens_list_str != NULL) { cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE); } free(sensorder); } int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_senscat *senscat = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_senscat_init(&senscat); senscat->sens_str = parse_current->next->data; rc = cil_fill_cats(parse_current->next->next, &senscat->cats); if (rc != SEPOL_OK) { goto exit; } ast_node->data = senscat; ast_node->flavor = CIL_SENSCAT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration"); cil_destroy_senscat(senscat); return rc; } void cil_destroy_senscat(struct cil_senscat *senscat) { if (senscat == NULL) { return; } cil_destroy_cats(senscat->cats); free(senscat); } int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_level *level = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_level_init(&level); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_level(parse_current->next->next->cl_head, level); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad level declaration"); cil_destroy_level(level); cil_clear_node(ast_node); return rc; } void cil_destroy_level(struct cil_level *level) { if (level == NULL) { return; } cil_symtab_datum_destroy(&level->datum); cil_destroy_cats(level->cats); free(level); } /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */ int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange) { enum cil_syntax syntax[] = { CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (low == NULL || lvlrange == NULL) { goto exit; } rc = __cil_verify_syntax(low, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (low->cl_head == NULL) { lvlrange->low_str = low->data; } else { cil_level_init(&lvlrange->low); rc = cil_fill_level(low->cl_head, lvlrange->low); if (rc != SEPOL_OK) { goto exit; } } if (low->next->cl_head == NULL) { lvlrange->high_str = low->next->data; } else { cil_level_init(&lvlrange->high); rc = cil_fill_level(low->next->cl_head, lvlrange->high); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad levelrange\n"); return rc; } int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_levelrange *lvlrange = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_levelrange_init(&lvlrange); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration"); cil_destroy_levelrange(lvlrange); cil_clear_node(ast_node); return rc; } void cil_destroy_levelrange(struct cil_levelrange *lvlrange) { if (lvlrange == NULL) { return; } cil_symtab_datum_destroy(&lvlrange->datum); if (lvlrange->low_str == NULL) { cil_destroy_level(lvlrange->low); } if (lvlrange->high_str == NULL) { cil_destroy_level(lvlrange->high); } free(lvlrange); } int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_constrain *cons = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_constrain_init(&cons); rc = cil_fill_classperms_list(parse_current->next, &cons->classperms); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = cons; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration"); cil_destroy_constrain(cons); return rc; } void cil_destroy_constrain(struct cil_constrain *cons) { if (cons == NULL) { return; } cil_destroy_classperms_list(&cons->classperms); cil_list_destroy(&cons->str_expr, CIL_TRUE); cil_list_destroy(&cons->datum_expr, CIL_FALSE); free(cons); } int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_validatetrans *validtrans = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_validatetrans_init(&validtrans); validtrans->class_str = parse_current->next->data; rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = validtrans; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration"); cil_destroy_validatetrans(validtrans); return rc; } void cil_destroy_validatetrans(struct cil_validatetrans *validtrans) { if (validtrans == NULL) { return; } cil_list_destroy(&validtrans->str_expr, CIL_TRUE); cil_list_destroy(&validtrans->datum_expr, CIL_FALSE); free(validtrans); } /* Fills in context starting from user */ int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (user_node == NULL || context == NULL) { goto exit; } rc = __cil_verify_syntax(user_node, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } context->user_str = user_node->data; context->role_str = user_node->next->data; context->type_str = user_node->next->next->data; context->range_str = NULL; if (user_node->next->next->next->cl_head == NULL) { context->range_str = user_node->next->next->next->data; } else { cil_levelrange_init(&context->range); rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad context\n"); return rc; } int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_context *context = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_context_init(&context); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_context(parse_current->next->next->cl_head, context); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad context declaration"); cil_destroy_context(context); cil_clear_node(ast_node); return SEPOL_ERR; } void cil_destroy_context(struct cil_context *context) { if (context == NULL) { return; } cil_symtab_datum_destroy(&context->datum);; if (context->range_str == NULL && context->range != NULL) { cil_destroy_levelrange(context->range); } free(context); } int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_filecon *filecon = NULL; char *type = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } type = parse_current->next->next->data; cil_filecon_init(&filecon); filecon->path_str = parse_current->next->data; if (type == CIL_KEY_FILE) { filecon->type = CIL_FILECON_FILE; } else if (type == CIL_KEY_DIR) { filecon->type = CIL_FILECON_DIR; } else if (type == CIL_KEY_CHAR) { filecon->type = CIL_FILECON_CHAR; } else if (type == CIL_KEY_BLOCK) { filecon->type = CIL_FILECON_BLOCK; } else if (type == CIL_KEY_SOCKET) { filecon->type = CIL_FILECON_SOCKET; } else if (type == CIL_KEY_PIPE) { filecon->type = CIL_FILECON_PIPE; } else if (type == CIL_KEY_SYMLINK) { filecon->type = CIL_FILECON_SYMLINK; } else if (type == CIL_KEY_ANY) { filecon->type = CIL_FILECON_ANY; } else { cil_log(CIL_ERR, "Invalid file type\n"); rc = SEPOL_ERR; goto exit; } if (parse_current->next->next->next->cl_head == NULL) { filecon->context_str = parse_current->next->next->next->data; } else { if (parse_current->next->next->next->cl_head->next == NULL) { filecon->context = NULL; } else { cil_context_init(&filecon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context); if (rc != SEPOL_OK) { goto exit; } } } ast_node->data = filecon; ast_node->flavor = CIL_FILECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); cil_destroy_filecon(filecon); return rc; } //TODO: Should we be checking if the pointer is NULL when passed in? void cil_destroy_filecon(struct cil_filecon *filecon) { if (filecon == NULL) { return; } if (filecon->context_str == NULL && filecon->context != NULL) { cil_destroy_context(filecon->context); } free(filecon); } int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibpkeycon *ibpkeycon = NULL; if (!parse_current || !ast_node) goto exit; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) goto exit; cil_ibpkeycon_init(&ibpkeycon); ibpkeycon->subnet_prefix_str = parse_current->next->data; if (parse_current->next->next->cl_head) { if (parse_current->next->next->cl_head->next && !parse_current->next->next->cl_head->next->next) { rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper ibpkey range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } ibpkeycon->pkey_high = ibpkeycon->pkey_low; } if (!parse_current->next->next->next->cl_head) { ibpkeycon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&ibpkeycon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context); if (rc != SEPOL_OK) goto exit; } ast_node->data = ibpkeycon; ast_node->flavor = CIL_IBPKEYCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration"); cil_destroy_ibpkeycon(ibpkeycon); return rc; } void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) { if (!ibpkeycon) return; if (!ibpkeycon->context_str && ibpkeycon->context) cil_destroy_context(ibpkeycon->context); free(ibpkeycon); } int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_portcon *portcon = NULL; char *proto; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_portcon_init(&portcon); proto = parse_current->next->data; if (proto == CIL_KEY_UDP) { portcon->proto = CIL_PROTOCOL_UDP; } else if (proto == CIL_KEY_TCP) { portcon->proto = CIL_PROTOCOL_TCP; } else if (proto == CIL_KEY_DCCP) { portcon->proto = CIL_PROTOCOL_DCCP; } else if (proto == CIL_KEY_SCTP) { portcon->proto = CIL_PROTOCOL_SCTP; } else { cil_log(CIL_ERR, "Invalid protocol\n"); rc = SEPOL_ERR; goto exit; } if (parse_current->next->next->cl_head != NULL) { if (parse_current->next->next->cl_head->next != NULL && parse_current->next->next->cl_head->next->next == NULL) { rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper port range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } portcon->port_high = portcon->port_low; } if (parse_current->next->next->next->cl_head == NULL ) { portcon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&portcon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = portcon; ast_node->flavor = CIL_PORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration"); cil_destroy_portcon(portcon); return rc; } void cil_destroy_portcon(struct cil_portcon *portcon) { if (portcon == NULL) { return; } if (portcon->context_str == NULL && portcon->context != NULL) { cil_destroy_context(portcon->context); } free(portcon); } int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_nodecon *nodecon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_nodecon_init(&nodecon); if (parse_current->next->cl_head == NULL ) { nodecon->addr_str = parse_current->next->data; } else { cil_ipaddr_init(&nodecon->addr); rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr); if (rc != SEPOL_OK) { goto exit; } } if (parse_current->next->next->cl_head == NULL ) { nodecon->mask_str = parse_current->next->next->data; } else { cil_ipaddr_init(&nodecon->mask); rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask); if (rc != SEPOL_OK) { goto exit; } } if (parse_current->next->next->next->cl_head == NULL ) { nodecon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&nodecon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = nodecon; ast_node->flavor = CIL_NODECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration"); cil_destroy_nodecon(nodecon); return rc; } void cil_destroy_nodecon(struct cil_nodecon *nodecon) { if (nodecon == NULL) { return; } if (nodecon->addr_str == NULL && nodecon->addr != NULL) { cil_destroy_ipaddr(nodecon->addr); } if (nodecon->mask_str == NULL && nodecon->mask != NULL) { cil_destroy_ipaddr(nodecon->mask); } if (nodecon->context_str == NULL && nodecon->context != NULL) { cil_destroy_context(nodecon->context); } free(nodecon); } int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_genfscon *genfscon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_genfscon_init(&genfscon); genfscon->fs_str = parse_current->next->data; genfscon->path_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL ) { genfscon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&genfscon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = genfscon; ast_node->flavor = CIL_GENFSCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration"); cil_destroy_genfscon(genfscon); return SEPOL_ERR; } void cil_destroy_genfscon(struct cil_genfscon *genfscon) { if (genfscon == NULL) { return; } if (genfscon->context_str == NULL && genfscon->context != NULL) { cil_destroy_context(genfscon->context); } free(genfscon); } int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_netifcon *netifcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_netifcon_init(&netifcon); netifcon->interface_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { netifcon->if_context_str = parse_current->next->next->data; } else { cil_context_init(&netifcon->if_context); rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context); if (rc != SEPOL_OK) { goto exit; } } if (parse_current->next->next->next->cl_head == NULL) { netifcon->packet_context_str = parse_current->next->next->next->data; } else { cil_context_init(&netifcon->packet_context); rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = netifcon; ast_node->flavor = CIL_NETIFCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration"); cil_destroy_netifcon(netifcon); return SEPOL_ERR; } void cil_destroy_netifcon(struct cil_netifcon *netifcon) { if (netifcon == NULL) { return; } if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) { cil_destroy_context(netifcon->if_context); } if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) { cil_destroy_context(netifcon->packet_context); } free(netifcon); } int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibendportcon *ibendportcon = NULL; if (!parse_current || !ast_node) goto exit; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) goto exit; cil_ibendportcon_init(&ibendportcon); ibendportcon->dev_name_str = parse_current->next->data; rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibendport port specified\n"); goto exit; } if (!parse_current->next->next->next->cl_head) { ibendportcon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&ibendportcon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context); if (rc != SEPOL_OK) goto exit; } ast_node->data = ibendportcon; ast_node->flavor = CIL_IBENDPORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration"); cil_destroy_ibendportcon(ibendportcon); return SEPOL_ERR; } void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon) { if (!ibendportcon) return; if (!ibendportcon->context_str && ibendportcon->context) cil_destroy_context(ibendportcon->context); free(ibendportcon); } int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pirqcon *pirqcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_pirqcon_init(&pirqcon); rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next->cl_head == NULL) { pirqcon->context_str = parse_current->next->next->data; } else { cil_context_init(&pirqcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = pirqcon; ast_node->flavor = CIL_PIRQCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration"); cil_destroy_pirqcon(pirqcon); return rc; } void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon == NULL) { return; } if (pirqcon->context_str == NULL && pirqcon->context != NULL) { cil_destroy_context(pirqcon->context); } free(pirqcon); } int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_iomemcon *iomemcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_iomemcon_init(&iomemcon); if (parse_current->next->cl_head != NULL) { if (parse_current->next->cl_head->next != NULL && parse_current->next->cl_head->next->next == NULL) { rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper iomem range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } iomemcon->iomem_high = iomemcon->iomem_low; } if (parse_current->next->next->cl_head == NULL ) { iomemcon->context_str = parse_current->next->next->data; } else { cil_context_init(&iomemcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = iomemcon; ast_node->flavor = CIL_IOMEMCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration"); cil_destroy_iomemcon(iomemcon); return rc; } void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon == NULL) { return; } if (iomemcon->context_str == NULL && iomemcon->context != NULL) { cil_destroy_context(iomemcon->context); } free(iomemcon); } int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ioportcon *ioportcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_ioportcon_init(&ioportcon); if (parse_current->next->cl_head != NULL) { if (parse_current->next->cl_head->next != NULL && parse_current->next->cl_head->next->next == NULL) { rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper ioport range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } ioportcon->ioport_high = ioportcon->ioport_low; } if (parse_current->next->next->cl_head == NULL ) { ioportcon->context_str = parse_current->next->next->data; } else { cil_context_init(&ioportcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = ioportcon; ast_node->flavor = CIL_IOPORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration"); cil_destroy_ioportcon(ioportcon); return rc; } void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon == NULL) { return; } if (ioportcon->context_str == NULL && ioportcon->context != NULL) { cil_destroy_context(ioportcon->context); } free(ioportcon); } int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pcidevicecon *pcidevicecon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_pcidevicecon_init(&pcidevicecon); rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next->cl_head == NULL) { pcidevicecon->context_str = parse_current->next->next->data; } else { cil_context_init(&pcidevicecon->context); rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = pcidevicecon; ast_node->flavor = CIL_PCIDEVICECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration"); cil_destroy_pcidevicecon(pcidevicecon); return rc; } void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon == NULL) { return; } if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) { cil_destroy_context(pcidevicecon->context); } free(pcidevicecon); } int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_devicetreecon *devicetreecon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_devicetreecon_init(&devicetreecon); devicetreecon->path = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { devicetreecon->context_str = parse_current->next->next->data; } else { cil_context_init(&devicetreecon->context); rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = devicetreecon; ast_node->flavor = CIL_DEVICETREECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration"); cil_destroy_devicetreecon(devicetreecon); return rc; } void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon == NULL) { return; } if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) { cil_destroy_context(devicetreecon->context); } free(devicetreecon); } int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *type = NULL; struct cil_fsuse *fsuse = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } type = parse_current->next->data; cil_fsuse_init(&fsuse); if (type == CIL_KEY_XATTR) { fsuse->type = CIL_FSUSE_XATTR; } else if (type == CIL_KEY_TASK) { fsuse->type = CIL_FSUSE_TASK; } else if (type == CIL_KEY_TRANS) { fsuse->type = CIL_FSUSE_TRANS; } else { cil_log(CIL_ERR, "Invalid fsuse type\n"); goto exit; } fsuse->fs_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { fsuse->context_str = parse_current->next->next->next->data; } else { cil_context_init(&fsuse->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = fsuse; ast_node->flavor = CIL_FSUSE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration"); cil_destroy_fsuse(fsuse); return SEPOL_ERR; } void cil_destroy_fsuse(struct cil_fsuse *fsuse) { if (fsuse == NULL) { return; } if (fsuse->context_str == NULL && fsuse->context != NULL) { cil_destroy_context(fsuse->context); } free(fsuse); } void cil_destroy_param(struct cil_param *param) { if (param == NULL) { return; } free(param); } int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; char *key = NULL; struct cil_macro *macro = NULL; struct cil_tree_node *macro_content = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/ sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc =__cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_macro_init(¯o); key = parse_current->next->data; struct cil_tree_node *current_item = parse_current->next->next->cl_head; while (current_item != NULL) { enum cil_syntax param_syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax); char *kind = NULL; struct cil_param *param = NULL; rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); if (rc != SEPOL_OK) { goto exit; } if (macro->params == NULL) { cil_list_init(¯o->params, CIL_LIST_ITEM); } kind = current_item->cl_head->data; cil_param_init(¶m); if (kind == CIL_KEY_TYPE) { param->flavor = CIL_TYPE; } else if (kind == CIL_KEY_ROLE) { param->flavor = CIL_ROLE; } else if (kind == CIL_KEY_USER) { param->flavor = CIL_USER; } else if (kind == CIL_KEY_SENSITIVITY) { param->flavor = CIL_SENS; } else if (kind == CIL_KEY_CATEGORY) { param->flavor = CIL_CAT; } else if (kind == CIL_KEY_CATSET) { param->flavor = CIL_CATSET; } else if (kind == CIL_KEY_LEVEL) { param->flavor = CIL_LEVEL; } else if (kind == CIL_KEY_LEVELRANGE) { param->flavor = CIL_LEVELRANGE; } else if (kind == CIL_KEY_CLASS) { param->flavor = CIL_CLASS; } else if (kind == CIL_KEY_IPADDR) { param->flavor = CIL_IPADDR; } else if (kind == CIL_KEY_MAP_CLASS) { param->flavor = CIL_MAP_CLASS; } else if (kind == CIL_KEY_CLASSPERMISSION) { param->flavor = CIL_CLASSPERMISSION; } else if (kind == CIL_KEY_BOOL) { param->flavor = CIL_BOOL; } else if (kind == CIL_KEY_STRING) { param->flavor = CIL_NAME; } else if (kind == CIL_KEY_NAME) { param->flavor = CIL_NAME; } else { cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind); cil_destroy_param(param); goto exit; } param->str = current_item->cl_head->next->data; rc = __cil_verify_name(param->str); if (rc != SEPOL_OK) { cil_destroy_param(param); goto exit; } //walk current list and check for duplicate parameters struct cil_list_item *curr_param; cil_list_for_each(curr_param, macro->params) { if (param->str == ((struct cil_param*)curr_param->data)->str) { if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) { cil_log(CIL_ERR, "Duplicate parameter\n"); cil_destroy_param(param); goto exit; } } } cil_list_append(macro->params, CIL_PARAM, param); current_item = current_item->next; } /* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the node containing the macro name is updated to point to the start of the macro content */ macro_content = parse_current->next->next->next; cil_tree_subtree_destroy(parse_current->next->next); parse_current->next->next = macro_content; if (macro_content == NULL) { /* No statements in macro and macro parameter list was last node */ parse_current->parent->cl_tail = parse_current->next; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration"); cil_destroy_macro(macro); cil_clear_node(ast_node); return SEPOL_ERR; } void cil_destroy_macro(struct cil_macro *macro) { if (macro == NULL) { return; } cil_symtab_datum_destroy(¯o->datum); cil_symtab_array_destroy(macro->symtab); if (macro->params != NULL) { cil_list_destroy(¯o->params, 1); } free(macro); } int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_call *call = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_call_init(&call); call->macro_str = parse_current->next->data; if (parse_current->next->next != NULL) { cil_tree_init(&call->args_tree); cil_copy_ast(db, parse_current->next->next, call->args_tree->root); } ast_node->data = call; ast_node->flavor = CIL_CALL; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad macro call"); cil_destroy_call(call); return rc; } void cil_destroy_call(struct cil_call *call) { if (call == NULL) { return; } call->macro = NULL; if (call->args_tree != NULL) { cil_tree_destroy(&call->args_tree); } if (call->args != NULL) { cil_list_destroy(&call->args, 1); } free(call); } void cil_destroy_args(struct cil_args *args) { if (args == NULL) { return; } if (args->arg_str != NULL) { args->arg_str = NULL; } else if (args->arg != NULL) { struct cil_tree_node *node = args->arg->nodes->head->data; switch (args->flavor) { case CIL_NAME: break; case CIL_CATSET: cil_destroy_catset((struct cil_catset *)args->arg); free(node); break; case CIL_LEVEL: cil_destroy_level((struct cil_level *)args->arg); free(node); break; case CIL_LEVELRANGE: cil_destroy_levelrange((struct cil_levelrange *)args->arg); free(node); break; case CIL_IPADDR: cil_destroy_ipaddr((struct cil_ipaddr *)args->arg); free(node); break; case CIL_CLASSPERMISSION: cil_destroy_classpermission((struct cil_classpermission *)args->arg); free(node); break; default: cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor); break; } } args->param_str = NULL; args->arg = NULL; free(args); } int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_optional *optional = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_optional_init(&optional); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL); if (rc != SEPOL_OK) goto exit; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad optional"); cil_destroy_optional(optional); cil_clear_node(ast_node); return rc; } void cil_destroy_optional(struct cil_optional *optional) { if (optional == NULL) { return; } cil_symtab_datum_destroy(&optional->datum); free(optional); } int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_policycap *polcap = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_policycap_init(&polcap); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP); if (rc != SEPOL_OK) goto exit; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement"); cil_destroy_policycap(polcap); cil_clear_node(ast_node); return rc; } void cil_destroy_policycap(struct cil_policycap *polcap) { if (polcap == NULL) { return; } cil_symtab_datum_destroy(&polcap->datum); free(polcap); } int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_ipaddr *ipaddr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_ipaddr_init(&ipaddr); key = parse_current->next->data; rc = cil_fill_ipaddr(parse_current->next->next, ipaddr); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement"); cil_destroy_ipaddr(ipaddr); cil_clear_node(ast_node); return rc; } void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr) { if (ipaddr == NULL) { return; } cil_symtab_datum_destroy(&ipaddr->datum); free(ipaddr); } int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base) { int rc = SEPOL_ERR; char *endptr = NULL; int val; if (int_node == NULL || integer == NULL) { goto exit; } errno = 0; val = strtol(int_node->data, &endptr, base); if (errno != 0 || endptr == int_node->data || *endptr != '\0') { rc = SEPOL_ERR; goto exit; } *integer = val; return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to create integer from string\n"); return rc; } int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base) { int rc = SEPOL_ERR; char *endptr = NULL; uint64_t val; if (int_node == NULL || integer == NULL) { goto exit; } errno = 0; val = strtoull(int_node->data, &endptr, base); if (errno != 0 || endptr == int_node->data || *endptr != '\0') { rc = SEPOL_ERR; goto exit; } *integer = val; return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to create integer from string\n"); return rc; } int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) { int rc = SEPOL_ERR; if (addr_node == NULL || addr == NULL) { goto exit; } if (addr_node->cl_head != NULL || addr_node->next != NULL) { goto exit; } if (strchr(addr_node->data, '.') != NULL) { addr->family = AF_INET; } else { addr->family = AF_INET6; } rc = inet_pton(addr->family, addr_node->data, &addr->ip); if (rc != 1) { rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad ip address or netmask\n"); return rc; } int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); if (curr == NULL) { goto exit; } rc = __cil_verify_syntax(curr, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } level->sens_str = curr->data; if (curr->next != NULL) { rc = cil_fill_cats(curr->next, &level->cats); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad level\n"); return rc; } int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats) { int rc = SEPOL_ERR; cil_cats_init(cats); rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr); if (rc != SEPOL_OK) { cil_destroy_cats(*cats); *cats = NULL; } return rc; } void cil_destroy_cats(struct cil_cats *cats) { if (cats == NULL) { return; } cil_list_destroy(&cats->str_expr, CIL_TRUE); cil_list_destroy(&cats->datum_expr, CIL_FALSE); free(cats); } int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_bounds *bounds = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_bounds_init(&bounds); bounds->parent_str = parse_current->next->data; bounds->child_str = parse_current->next->next->data; ast_node->data = bounds; switch (flavor) { case CIL_USER: ast_node->flavor = CIL_USERBOUNDS; break; case CIL_ROLE: ast_node->flavor = CIL_ROLEBOUNDS; break; case CIL_TYPE: ast_node->flavor = CIL_TYPEBOUNDS; break; default: break; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration"); cil_destroy_bounds(bounds); return rc; } void cil_destroy_bounds(struct cil_bounds *bounds) { if (bounds == NULL) { return; } free(bounds); } int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { int rc = SEPOL_ERR; struct cil_default *def = NULL; char *object; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_default_init(&def); def->flavor = flavor; if (parse_current->next->cl_head == NULL) { cil_list_init(&def->class_strs, CIL_CLASS); cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); if (rc != SEPOL_OK) { goto exit; } } object = parse_current->next->next->data; if (object == CIL_KEY_SOURCE) { def->object = CIL_DEFAULT_SOURCE; } else if (object == CIL_KEY_TARGET) { def->object = CIL_DEFAULT_TARGET; } else { cil_log(CIL_ERR,"Expected either 'source' or 'target'\n"); rc = SEPOL_ERR; goto exit; } ast_node->data = def; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current)); cil_destroy_default(def); return rc; } void cil_destroy_default(struct cil_default *def) { if (def == NULL) { return; } cil_list_destroy(&def->class_strs, CIL_TRUE); cil_list_destroy(&def->class_datums, CIL_FALSE); free(def); } int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_defaultrange *def = NULL; char *object; char *range; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_defaultrange_init(&def); if (parse_current->next->cl_head == NULL) { cil_list_init(&def->class_strs, CIL_CLASS); cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); if (rc != SEPOL_OK) { goto exit; } } object = parse_current->next->next->data; range = parse_current->next->next->next->data; if (object == CIL_KEY_SOURCE) { if (range == CIL_KEY_LOW) { def->object_range = CIL_DEFAULT_SOURCE_LOW; } else if (range == CIL_KEY_HIGH) { def->object_range = CIL_DEFAULT_SOURCE_HIGH; } else if (range == CIL_KEY_LOW_HIGH) { def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH; } else { cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); rc = SEPOL_ERR; goto exit; } } else if (parse_current->next->next->data == CIL_KEY_TARGET) { if (range == CIL_KEY_LOW) { def->object_range = CIL_DEFAULT_TARGET_LOW; } else if (range == CIL_KEY_HIGH) { def->object_range = CIL_DEFAULT_TARGET_HIGH; } else if (range == CIL_KEY_LOW_HIGH) { def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH; } else { cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n"); rc = SEPOL_ERR; goto exit; } ast_node->data = def; ast_node->flavor = CIL_DEFAULTRANGE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration"); cil_destroy_defaultrange(def); return rc; } void cil_destroy_defaultrange(struct cil_defaultrange *def) { if (def == NULL) { return; } cil_list_destroy(&def->class_strs, CIL_TRUE); cil_list_destroy(&def->class_datums, CIL_FALSE); free(def); } int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_handleunknown *unknown = NULL; char *unknown_key; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_handleunknown_init(&unknown); unknown_key = parse_current->next->data; if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) { unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN; } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) { unknown->handle_unknown = SEPOL_DENY_UNKNOWN; } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) { unknown->handle_unknown = SEPOL_REJECT_UNKNOWN; } else { cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT); rc = SEPOL_ERR; goto exit; } ast_node->data = unknown; ast_node->flavor = CIL_HANDLEUNKNOWN; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown"); cil_destroy_handleunknown(unknown); return rc; } void cil_destroy_handleunknown(struct cil_handleunknown *unk) { free(unk); } int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_mls *mls = NULL; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_mls_init(&mls); if (parse_current->next->data == CIL_KEY_CONDTRUE) { mls->value = CIL_TRUE; } else if (parse_current->next->data == CIL_KEY_CONDFALSE) { mls->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } ast_node->data = mls; ast_node->flavor = CIL_MLS; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad mls"); cil_destroy_mls(mls); return rc; } void cil_destroy_mls(struct cil_mls *mls) { free(mls); } int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { /* No need to check syntax, because this is auto generated */ struct cil_src_info *info = NULL; cil_src_info_init(&info); info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE; info->path = parse_current->next->next->data; ast_node->data = info; ast_node->flavor = CIL_SRC_INFO; return SEPOL_OK; } void cil_destroy_src_info(struct cil_src_info *info) { free(info); } int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) { struct cil_args_build *args = NULL; struct cil_tree_node *ast_current = NULL; struct cil_db *db = NULL; struct cil_tree_node *ast_node = NULL; struct cil_tree_node *macro = NULL; struct cil_tree_node *boolif = NULL; struct cil_tree_node *tunif = NULL; struct cil_tree_node *in = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || finished == NULL || extra_args == NULL) { goto exit; } args = extra_args; ast_current = args->ast; db = args->db; macro = args->macro; boolif = args->boolif; tunif = args->tunif; in = args->in; if (parse_current->parent->cl_head != parse_current) { /* ignore anything that isn't following a parenthesis */ rc = SEPOL_OK; goto exit; } else if (parse_current->data == NULL) { /* the only time parenthsis can immediately following parenthesis is if * the parent is the root node */ if (parse_current->parent->parent == NULL) { rc = SEPOL_OK; } else { cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); } goto exit; } if (macro != NULL) { if (parse_current->data == CIL_KEY_MACRO || parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN || parse_current->data == CIL_KEY_BLOCK || parse_current->data == CIL_KEY_BLOCKINHERIT || parse_current->data == CIL_KEY_BLOCKABSTRACT) { rc = SEPOL_ERR; cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data); goto exit; } } if (boolif != NULL) { if (parse_current->data != CIL_KEY_CONDTRUE && parse_current->data != CIL_KEY_CONDFALSE && parse_current->data != CIL_KEY_AUDITALLOW && parse_current->data != CIL_KEY_TUNABLEIF && parse_current->data != CIL_KEY_ALLOW && parse_current->data != CIL_KEY_DONTAUDIT && parse_current->data != CIL_KEY_TYPETRANSITION && parse_current->data != CIL_KEY_TYPECHANGE && parse_current->data != CIL_KEY_CALL) { rc = SEPOL_ERR; cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data); if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n", (char*)parse_current->data); } else { cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n", (char*)parse_current->data); } goto exit; } } if (tunif != NULL) { if (parse_current->data == CIL_KEY_TUNABLE) { rc = SEPOL_ERR; cil_tree_log(parse_current, CIL_ERR, "Found tunable"); cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n"); goto exit; } } if (in != NULL) { if (parse_current->data == CIL_KEY_IN) { rc = SEPOL_ERR; cil_tree_log(parse_current, CIL_ERR, "Found in-statement"); cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n"); goto exit; } } cil_tree_node_init(&ast_node); ast_node->parent = ast_current; ast_node->line = parse_current->line; ast_node->hll_line = parse_current->hll_line; if (parse_current->data == CIL_KEY_BLOCK) { rc = cil_gen_block(db, parse_current, ast_node, 0); } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) { rc = cil_gen_blockinherit(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) { rc = cil_gen_blockabstract(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_IN) { rc = cil_gen_in(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_CLASS) { rc = cil_gen_class(db, parse_current, ast_node); // To avoid parsing list of perms again *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CLASSORDER) { rc = cil_gen_classorder(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_MAP_CLASS) { rc = cil_gen_map_class(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { rc = cil_gen_classmapping(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) { rc = cil_gen_classpermission(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) { rc = cil_gen_classpermissionset(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_COMMON) { rc = cil_gen_common(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CLASSCOMMON) { rc = cil_gen_classcommon(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_SID) { rc = cil_gen_sid(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { rc = cil_gen_sidcontext(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SIDORDER) { rc = cil_gen_sidorder(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_USER) { rc = cil_gen_user(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { rc = cil_gen_userattribute(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) { rc = cil_gen_userattributeset(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_USERLEVEL) { rc = cil_gen_userlevel(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_USERRANGE) { rc = cil_gen_userrange(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_USERBOUNDS) { rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER); } else if (parse_current->data == CIL_KEY_USERPREFIX) { rc = cil_gen_userprefix(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_SELINUXUSER) { rc = cil_gen_selinuxuser(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) { rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_TYPE) { rc = cil_gen_type(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) { rc = cil_gen_typeattribute(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) { rc = cil_gen_typeattributeset(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) { rc = cil_gen_expandtypeattribute(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_TYPEALIAS) { rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS); } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL); } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) { rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE); } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) { rc = cil_gen_typepermissive(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_RANGETRANSITION) { rc = cil_gen_rangetransition(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_ROLE) { rc = cil_gen_role(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_USERROLE) { rc = cil_gen_userrole(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_ROLETYPE) { rc = cil_gen_roletype(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_ROLETRANSITION) { rc = cil_gen_roletransition(parse_current, ast_node); } else if (parse_current->data == CIL_KEY_ROLEALLOW) { rc = cil_gen_roleallow(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) { rc = cil_gen_roleattribute(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) { rc = cil_gen_roleattributeset(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) { rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE); } else if (parse_current->data == CIL_KEY_BOOL) { rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE); } else if (parse_current->data == CIL_KEY_BOOLEANIF) { rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE); } else if(parse_current->data == CIL_KEY_TUNABLE) { if (db->preserve_tunables) { rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE); } else { rc = cil_gen_tunable(db, parse_current, ast_node); } } else if (parse_current->data == CIL_KEY_TUNABLEIF) { if (db->preserve_tunables) { rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE); } else { rc = cil_gen_tunif(db, parse_current, ast_node); } } else if (parse_current->data == CIL_KEY_CONDTRUE) { rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE); } else if (parse_current->data == CIL_KEY_CONDFALSE) { rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE); } else if (parse_current->data == CIL_KEY_ALLOW) { rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED); // So that the object and perms lists do not get parsed again *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_AUDITALLOW) { rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DONTAUDIT) { rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_NEVERALLOW) { rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_ALLOWX) { rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_AUDITALLOWX) { rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DONTAUDITX) { rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_NEVERALLOWX) { rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_PERMISSIONX) { rc = cil_gen_permissionx(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { rc = cil_gen_typetransition(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_TYPECHANGE) { rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE); } else if (parse_current->data == CIL_KEY_TYPEMEMBER) { rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER); } else if (parse_current->data == CIL_KEY_SENSITIVITY) { rc = cil_gen_sensitivity(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_SENSALIAS) { rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS); } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATEGORY) { rc = cil_gen_category(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_CATALIAS) { rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS); } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATSET) { rc = cil_gen_catset(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CATORDER) { rc = cil_gen_catorder(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { rc = cil_gen_sensitivityorder(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SENSCAT) { rc = cil_gen_senscat(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_LEVEL) { rc = cil_gen_level(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_LEVELRANGE) { rc = cil_gen_levelrange(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CONSTRAIN) { rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) { rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_VALIDATETRANS) { rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) { rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_CONTEXT) { rc = cil_gen_context(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_FILECON) { rc = cil_gen_filecon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_IBPKEYCON) { rc = cil_gen_ibpkeycon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_IBENDPORTCON) { rc = cil_gen_ibendportcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_PORTCON) { rc = cil_gen_portcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_NODECON) { rc = cil_gen_nodecon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_GENFSCON) { rc = cil_gen_genfscon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_NETIFCON) { rc = cil_gen_netifcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_PIRQCON) { rc = cil_gen_pirqcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_IOMEMCON) { rc = cil_gen_iomemcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_IOPORTCON) { rc = cil_gen_ioportcon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_PCIDEVICECON) { rc = cil_gen_pcidevicecon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DEVICETREECON) { rc = cil_gen_devicetreecon(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_FSUSE) { rc = cil_gen_fsuse(db, parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_MACRO) { rc = cil_gen_macro(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_CALL) { rc = cil_gen_call(db, parse_current, ast_node); *finished = 1; } else if (parse_current->data == CIL_KEY_POLICYCAP) { rc = cil_gen_policycap(db, parse_current, ast_node); *finished = 1; } else if (parse_current->data == CIL_KEY_OPTIONAL) { rc = cil_gen_optional(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_IPADDR) { rc = cil_gen_ipaddr(db, parse_current, ast_node); } else if (parse_current->data == CIL_KEY_DEFAULTUSER) { rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DEFAULTROLE) { rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) { rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) { rc = cil_gen_defaultrange(parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) { rc = cil_gen_handleunknown(parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_MLS) { rc = cil_gen_mls(parse_current, ast_node); *finished = CIL_TREE_SKIP_NEXT; } else if (parse_current->data == CIL_KEY_SRC_INFO) { rc = cil_gen_src_info(parse_current, ast_node); } else { cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); rc = SEPOL_ERR; } if (rc == SEPOL_OK) { if (ast_current->cl_head == NULL) { if (ast_current->flavor == CIL_MACRO) { args->macro = ast_current; } if (ast_current->flavor == CIL_BOOLEANIF) { args->boolif = ast_current; } if (ast_current->flavor == CIL_TUNABLEIF) { args->tunif = ast_current; } if (ast_current->flavor == CIL_IN) { args->in = ast_current; } ast_current->cl_head = ast_node; } else { ast_current->cl_tail->next = ast_node; } ast_current->cl_tail = ast_node; ast_current = ast_node; args->ast = ast_current; } else { cil_tree_node_destroy(&ast_node); } exit: return rc; } int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args) { int rc = SEPOL_ERR; struct cil_tree_node *ast = NULL; struct cil_args_build *args = NULL; if (extra_args == NULL) { goto exit; } args = extra_args; ast = args->ast; if (ast->flavor == CIL_ROOT) { rc = SEPOL_OK; goto exit; } args->ast = ast->parent; if (ast->flavor == CIL_MACRO) { args->macro = NULL; } if (ast->flavor == CIL_BOOLEANIF) { args->boolif = NULL; } if (ast->flavor == CIL_TUNABLEIF) { args->tunif = NULL; } if (ast->flavor == CIL_IN) { args->in = NULL; } // At this point we no longer have any need for parse_current or any of its // siblings; they have all been converted to the appropriate AST node. The // full parse tree will get deleted elsewhere, but in an attempt to // minimize memory useage (of which the parse tree uses alot), start // deleting the parts we don't need now. cil_tree_children_destroy(parse_current->parent); return SEPOL_OK; exit: return rc; } int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast) { int rc = SEPOL_ERR; struct cil_args_build extra_args; if (db == NULL || parse_tree == NULL || ast == NULL) { goto exit; } extra_args.ast = ast; extra_args.db = db; extra_args.macro = NULL; extra_args.boolif = NULL; extra_args.tunif = NULL; extra_args.in = NULL; rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } libsepol/cil/src/cil_build_ast.h0100644 0000000 0000000 00000044133 13756670064 015745 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_BUILD_AST_H_ #define CIL_BUILD_AST_H_ #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_tree.h" #include "cil_list.h" int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor); int cil_parse_to_list(struct cil_tree_node *parse_cl_head, struct cil_list *ast_cl, enum cil_flavor flavor); int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract); void cil_destroy_block(struct cil_block *block); int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_blockinherit(struct cil_blockinherit *inherit); int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_blockabstract(struct cil_blockabstract *abstract); int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_in(struct cil_in *in); int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_class(struct cil_class *class); int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_classorder(struct cil_classorder *classorder); int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms); void cil_destroy_perm(struct cil_perm *perm); int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms); int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perm_strs); int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp); void cil_destroy_classperms(struct cil_classperms *cp); void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set); void cil_destroy_classperms_set(struct cil_classperms_set *cp_set); int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **expr_list); void cil_destroy_classperms_list(struct cil_list **cp_list); int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_classpermission(struct cil_classpermission *cp); int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_classpermissionset(struct cil_classpermissionset *cps); int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_classmapping(struct cil_classmapping *mapping); int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_classcommon(struct cil_classcommon *clscom); int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sid(struct cil_sid *sid); int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sidcontext(struct cil_sidcontext *sidcon); int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sidorder(struct cil_sidorder *sidorder); int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_user(struct cil_user *user); int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userattribute(struct cil_userattribute *attr); int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userattributeset(struct cil_userattributeset *attrset); int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userlevel(struct cil_userlevel *usrlvl); int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userrange(struct cil_userrange *userrange); int cil_gen_userbounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userprefix(struct cil_userprefix *userprefix); int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser); int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_role(struct cil_role *role); int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roletype(struct cil_roletype *roletype); int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userrole(struct cil_userrole *userrole); int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roletransition(struct cil_roletransition *roletrans); int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleallow(struct cil_roleallow *roleallow); int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleattribute(struct cil_roleattribute *role); int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset); int cil_gen_rolebounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); void cil_destroy_avrule(struct cil_avrule *rule); int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_permissionx(struct cil_permissionx *permx); int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); void cil_destroy_type_rule(struct cil_type_rule *rule); int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_type(struct cil_type *type); int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_typeattribute(struct cil_typeattribute *type); int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif); void cil_destroy_bool(struct cil_bool *boolean); int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_tunable(struct cil_tunable *tunable); int cil_gen_constrain_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **stack); int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **stack); int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunable_if); void cil_destroy_boolif(struct cil_booleanif *bif); int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_tunif(struct cil_tunableif *tif); int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_condblock(struct cil_condblock *cb); int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_alias(struct cil_alias *alias); int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual); int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_typeattributeset(struct cil_typeattributeset *attrtypes); int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr); int cil_gen_typebounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_typepermissive(struct cil_typepermissive *typeperm); int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_name(struct cil_name *name); void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans); int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans); int cil_gen_sensitivity(struct cil_db *idb, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sensitivity(struct cil_sens *sens); int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_category(struct cil_cat *cat); int cil_set_to_list(struct cil_tree_node *parse_current, struct cil_list *ast_cl); void cil_destroy_catset(struct cil_catset *catset); int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_catorder(struct cil_catorder *catorder); int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder); int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_senscat(struct cil_senscat *senscat); int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_level(struct cil_level *level); int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange); int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_levelrange(struct cil_levelrange *lvlrange); void cil_destroy_constrain_node(struct cil_tree_node *cons_node); int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_constrain(struct cil_constrain *cons); int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_validatetrans(struct cil_validatetrans *validtrans); int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context); int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_context(struct cil_context *context); int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_filecon(struct cil_filecon *filecon); int cil_gen_ibpkeycon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon); int cil_gen_ibendportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon); int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_portcon(struct cil_portcon *portcon); int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_nodecon(struct cil_nodecon *nodecon); int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_genfscon(struct cil_genfscon *genfscon); int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_netifcon(struct cil_netifcon *netifcon); int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon); int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon); int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon); int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon); int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon); int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_fsuse(struct cil_fsuse *fsuse); void cil_destroy_param(struct cil_param *param); int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_macro(struct cil_macro *macro); int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_call(struct cil_call *call); void cil_destroy_args(struct cil_args *args); int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_optional(struct cil_optional *optional); int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_policycap(struct cil_policycap *polcap); int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr); int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_bounds(struct cil_bounds *bounds); int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_default(struct cil_default *def); int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_handleunknown(struct cil_handleunknown *unk); int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_mls(struct cil_mls *mls); int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_defaultrange(struct cil_defaultrange *def); int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_src_info(struct cil_src_info *info); int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats); void cil_destroy_cats(struct cil_cats *cats); int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context); int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base); int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base); int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr); int cil_fill_level(struct cil_tree_node *sens, struct cil_level *level); int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast); #endif /* CIL_BUILD_AST_H_ */ libsepol/cil/src/cil_copy_ast.c0100644 0000000 0000000 00000144430 13756670064 015614 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" #include "cil_copy_ast.h" #include "cil_build_ast.h" #include "cil_strpool.h" struct cil_args_copy { struct cil_tree_node *dest; struct cil_db *db; }; void cil_copy_list(struct cil_list *data, struct cil_list **copy) { struct cil_list *new; struct cil_list_item *orig_item; cil_list_init(&new, data->flavor); cil_list_for_each(orig_item, data) { switch (orig_item->flavor) { case CIL_STRING: cil_list_append(new, CIL_STRING, orig_item->data); break; case CIL_LIST: { struct cil_list *new_sub = NULL; cil_copy_list((struct cil_list*)orig_item->data, &new_sub); cil_list_append(new, CIL_LIST, new_sub); break; } case CIL_PARAM: { struct cil_param *po = orig_item->data; struct cil_param *pn; cil_param_init(&pn); pn->str = po->str; pn->flavor = po->flavor; cil_list_append(new, CIL_PARAM, pn); } break; default: cil_list_append(new, orig_item->flavor, orig_item->data); break; } } *copy = new; } int cil_copy_node(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { char *new = NULL; if (data != NULL) { new = data; } *copy = new; return SEPOL_OK; } int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_block *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_block *new; cil_block_init(&new); *copy = new; } else { *copy = datum;; } return SEPOL_OK; } int cil_copy_blockabstract(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_blockabstract *orig = data; struct cil_blockabstract *new = NULL; cil_blockabstract_init(&new); new->block_str = orig->block_str; *copy = new; return SEPOL_OK; } int cil_copy_blockinherit(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_blockinherit *orig = data; struct cil_blockinherit *new = NULL; cil_blockinherit_init(&new); new->block_str = orig->block_str; new->block = orig->block; *copy = new; return SEPOL_OK; } int cil_copy_policycap(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_policycap *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_policycap *new; cil_policycap_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_perm(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_perm *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_perm *new; cil_perm_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } void cil_copy_classperms(struct cil_classperms *orig, struct cil_classperms **new) { cil_classperms_init(new); (*new)->class_str = orig->class_str; cil_copy_list(orig->perm_strs, &((*new)->perm_strs)); } void cil_copy_classperms_set(struct cil_classperms_set *orig, struct cil_classperms_set **new) { cil_classperms_set_init(new); (*new)->set_str = orig->set_str; } void cil_copy_classperms_list(struct cil_list *orig, struct cil_list **new) { struct cil_list_item *orig_item; if (orig == NULL) { return; } cil_list_init(new, CIL_LIST_ITEM); cil_list_for_each(orig_item, orig) { if (orig_item->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp; cil_copy_classperms(orig_item->data, &cp); cil_list_append(*new, CIL_CLASSPERMS, cp); } else { struct cil_classperms_set *cp_set; cil_copy_classperms_set(orig_item->data, &cp_set); cil_list_append(*new, CIL_CLASSPERMS_SET, cp_set); } } } int cil_copy_classmapping(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_classmapping *orig = data; struct cil_classmapping *new = NULL; cil_classmapping_init(&new); new->map_class_str = orig->map_class_str; new->map_perm_str = orig->map_perm_str; cil_copy_classperms_list(orig->classperms, &new->classperms); *copy = new; return SEPOL_OK; } int cil_copy_class(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_class *orig = data; struct cil_class *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_class: class cannot be redefined\n"); return SEPOL_ERR; } cil_class_init(&new); new->common = NULL; *copy = new; return SEPOL_OK; } int cil_copy_classorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_classorder *orig = data; struct cil_classorder *new = NULL; cil_classorder_init(&new); if (orig->class_list_str != NULL) { cil_copy_list(orig->class_list_str, &new->class_list_str); } *copy = new; return SEPOL_OK; } int cil_copy_classpermission(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_classpermission *orig = data; struct cil_classpermission *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; if (key != NULL) { cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "classpermission cannot be redefined\n"); return SEPOL_ERR; } } cil_classpermission_init(&new); cil_copy_classperms_list(orig->classperms, &new->classperms); *copy = new; return SEPOL_OK; } int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_classpermissionset *orig = data; struct cil_classpermissionset *new = NULL; cil_classpermissionset_init(&new); new->set_str = orig->set_str; cil_copy_classperms_list(orig->classperms, &new->classperms); *copy = new; return SEPOL_OK; } int cil_copy_classcommon(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_classcommon *orig = data; struct cil_classcommon *new = NULL; cil_classcommon_init(&new); new->class_str = orig->class_str; new->common_str = orig->common_str; *copy = new; return SEPOL_OK; } int cil_copy_sid(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_sid *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_sid *new; cil_sid_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_sidcontext *orig = data; struct cil_sidcontext *new = NULL; cil_sidcontext_init(&new); if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_sidorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_sidorder *orig = data; struct cil_sidorder *new = NULL; cil_sidorder_init(&new); if (orig->sid_list_str != NULL) { cil_copy_list(orig->sid_list_str, &new->sid_list_str); } *copy = new; return SEPOL_OK; } int cil_copy_user(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_user *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_user *new; cil_user_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_userattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_userattribute *orig = data; struct cil_userattribute *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { cil_userattribute_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userattributeset *orig = data; struct cil_userattributeset *new = NULL; cil_userattributeset_init(&new); new->attr_str = orig->attr_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userrole *orig = data; struct cil_userrole *new = NULL; cil_userrole_init(&new); new->user_str = orig->user_str; new->role_str = orig->role_str; *copy = new; return SEPOL_OK; } int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userlevel *orig = data; struct cil_userlevel *new = NULL; cil_userlevel_init(&new); new->user_str = orig->user_str; if (orig->level_str != NULL) { new->level_str = orig->level_str; } else { cil_copy_fill_level(db, orig->level, &new->level); } *copy = new; return SEPOL_OK; } int cil_copy_userrange(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userrange *orig = data; struct cil_userrange *new = NULL; cil_userrange_init(&new); new->user_str = orig->user_str; if (orig->range_str != NULL) { new->range_str = orig->range_str; } else { cil_levelrange_init(&new->range); cil_copy_fill_levelrange(db, orig->range, new->range); } *copy = new; return SEPOL_OK; } int cil_copy_userprefix(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userprefix *orig = data; struct cil_userprefix *new = NULL; cil_userprefix_init(&new); new->user_str = orig->user_str; new->prefix_str = orig->prefix_str; *copy = new; return SEPOL_OK; } int cil_copy_role(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_role *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_role *new; cil_role_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_roletype(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roletype *orig = data; struct cil_roletype *new = NULL; cil_roletype_init(&new); new->role_str = orig->role_str; new->type_str = orig->type_str; *copy = new; return SEPOL_OK; } int cil_copy_roleattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_roleattribute *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_roleattribute *new; cil_roleattribute_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_roleattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roleattributeset *orig = data; struct cil_roleattributeset *new = NULL; cil_roleattributeset_init(&new); new->attr_str = orig->attr_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roleallow *orig = data; struct cil_roleallow *new = NULL; cil_roleallow_init(&new); new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; *copy = new; return SEPOL_OK; } int cil_copy_type(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_type *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_type *new; cil_type_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_typepermissive(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_typepermissive *orig = data; struct cil_typepermissive *new = NULL; cil_typepermissive_init(&new); new->type_str = orig->type_str; *copy = new; return SEPOL_OK; } int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_typeattribute *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_typeattribute *new; cil_typeattribute_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_typeattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_typeattributeset *orig = data; struct cil_typeattributeset *new = NULL; cil_typeattributeset_init(&new); new->attr_str = orig->attr_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_expandtypeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_expandtypeattribute *orig = data; struct cil_expandtypeattribute *new = NULL; fprintf(stderr, "%s %u\n", __func__, __LINE__); cil_expandtypeattribute_init(&new); if (orig->attr_strs != NULL) { cil_copy_list(orig->attr_strs, &new->attr_strs); } if (orig->attr_datums != NULL) { cil_copy_list(orig->attr_datums, &new->attr_datums); } new->expand = orig->expand; *copy = new; return SEPOL_OK; } int cil_copy_alias(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_alias *orig = data; struct cil_alias *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_alias: alias cannot be redefined\n"); return SEPOL_ERR; } cil_alias_init(&new); *copy = new; return SEPOL_OK; } int cil_copy_aliasactual(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused))symtab_t *symtab) { struct cil_aliasactual *orig = data; struct cil_aliasactual *new = NULL; cil_aliasactual_init(&new); new->alias_str = orig->alias_str; new->actual_str = orig->actual_str; *copy = new; return SEPOL_OK; } int cil_copy_roletransition(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roletransition *orig = data; struct cil_roletransition *new = NULL; cil_roletransition_init(&new); new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; new->obj_str = orig->obj_str; new->result_str = orig->result_str; *copy = new; return SEPOL_OK; } int cil_copy_nametypetransition(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_nametypetransition *orig = data; struct cil_nametypetransition *new = NULL; cil_nametypetransition_init(&new); new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; new->obj_str = orig->obj_str; new->name_str = orig->name_str; new->result_str = orig->result_str; *copy = new; return SEPOL_OK; } int cil_copy_rangetransition(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_rangetransition *orig = data; struct cil_rangetransition *new = NULL; cil_rangetransition_init(&new); new->src_str = orig->src_str; new->exec_str = orig->exec_str; new->obj_str = orig->obj_str; if (orig->range_str != NULL) { new->range_str = orig->range_str; } else { cil_levelrange_init(&new->range); cil_copy_fill_levelrange(db, orig->range, new->range); } *copy = new; return SEPOL_OK; } int cil_copy_bool(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_bool *orig = data; struct cil_bool *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_bool: boolean cannot be redefined\n"); return SEPOL_ERR; } cil_bool_init(&new); new->value = orig->value; *copy = new; return SEPOL_OK; } int cil_copy_tunable(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_tunable *orig = data; struct cil_tunable *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_tunable: tunable cannot be redefined\n"); return SEPOL_ERR; } cil_tunable_init(&new); new->value = orig->value; *copy = new; return SEPOL_OK; } void cil_copy_fill_permissionx(struct cil_db *db, struct cil_permissionx *orig, struct cil_permissionx *new) { new->kind = orig->kind; new->obj_str = orig->obj_str; cil_copy_expr(db, orig->expr_str, &new->expr_str); } int cil_copy_avrule(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_avrule *orig = data; struct cil_avrule *new = NULL; cil_avrule_init(&new); new->is_extended = orig->is_extended; new->rule_kind = orig->rule_kind; new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; if (!new->is_extended) { cil_copy_classperms_list(orig->perms.classperms, &new->perms.classperms); } else { if (new->perms.x.permx_str != NULL) { new->perms.x.permx_str = orig->perms.x.permx_str; } else { cil_permissionx_init(&new->perms.x.permx); cil_copy_fill_permissionx(db, orig->perms.x.permx, new->perms.x.permx); } } *copy = new; return SEPOL_OK; } int cil_copy_permissionx(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_permissionx *orig = data; struct cil_permissionx *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_permissionx: permissionx cannot be redefined\n"); return SEPOL_ERR; } cil_permissionx_init(&new); cil_copy_fill_permissionx(db, orig, new); *copy = new; return SEPOL_OK; } int cil_copy_type_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_type_rule *orig = data; struct cil_type_rule *new = NULL; cil_type_rule_init(&new); new->rule_kind = orig->rule_kind; new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; new->obj_str = orig->obj_str; new->result_str = orig->result_str; *copy = new; return SEPOL_OK; } int cil_copy_sens(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_sens *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_sens *new; cil_sens_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_cat(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_cat *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_cat *new; cil_cat_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } void cil_copy_cats(struct cil_db *db, struct cil_cats *orig, struct cil_cats **new) { cil_cats_init(new); cil_copy_expr(db, orig->str_expr, &(*new)->str_expr); cil_copy_expr(db, orig->datum_expr, &(*new)->datum_expr); } int cil_copy_catset(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_catset *orig = data; struct cil_catset *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_catset: categoryset cannot be redefined\n"); return SEPOL_ERR; } cil_catset_init(&new); cil_copy_cats(db, orig->cats, &new->cats); *copy = new; return SEPOL_OK; } int cil_copy_senscat(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_senscat *orig = data; struct cil_senscat *new = NULL; cil_senscat_init(&new); new->sens_str = orig->sens_str; cil_copy_cats(db, orig->cats, &new->cats); *copy = new; return SEPOL_OK; } int cil_copy_catorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_catorder *orig = data; struct cil_catorder *new = NULL; cil_catorder_init(&new); if (orig->cat_list_str != NULL) { cil_copy_list(orig->cat_list_str, &new->cat_list_str); } *copy = new; return SEPOL_OK; } int cil_copy_sensitivityorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_sensorder *orig = data; struct cil_sensorder *new = NULL; cil_sensorder_init(&new); if (orig->sens_list_str != NULL) { cil_copy_list(orig->sens_list_str, &new->sens_list_str); } *copy = new; return SEPOL_OK; } void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new) { cil_level_init(new); (*new)->sens_str = orig->sens_str; if (orig->cats != NULL) { cil_copy_cats(db, orig->cats, &(*new)->cats); } } int cil_copy_level(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_level *orig = data; struct cil_level *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; if (key != NULL) { cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_level: level cannot be redefined\n"); return SEPOL_ERR; } } cil_copy_fill_level(db, orig, &new); *copy = new; return SEPOL_OK; } void cil_copy_fill_levelrange(struct cil_db *db, struct cil_levelrange *data, struct cil_levelrange *new) { if (data->low_str != NULL) { new->low_str = data->low_str; } else { cil_copy_fill_level(db, data->low, &new->low); } if (data->high_str != NULL) { new->high_str = data->high_str; } else { cil_copy_fill_level(db, data->high, &new->high); } } int cil_copy_levelrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_levelrange *orig = data; struct cil_levelrange *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; if (key != NULL) { cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_levelrange: levelrange cannot be redefined\n"); return SEPOL_ERR; } } cil_levelrange_init(&new); cil_copy_fill_levelrange(db, orig, new); *copy = new; return SEPOL_OK; } void cil_copy_fill_context(struct cil_db *db, struct cil_context *data, struct cil_context *new) { new->user_str = data->user_str; new->role_str = data->role_str; new->type_str = data->type_str; if (data->range_str != NULL) { new->range_str = data->range_str; } else { cil_levelrange_init(&new->range); cil_copy_fill_levelrange(db, data->range, new->range); } } int cil_copy_context(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_context *orig = data; struct cil_context *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; if (key != NULL) { cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_context: context cannot be redefined\n"); return SEPOL_ERR; } } cil_context_init(&new); cil_copy_fill_context(db, orig, new); *copy = new; return SEPOL_OK; } int cil_copy_netifcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_netifcon *orig = data; struct cil_netifcon *new = NULL; cil_netifcon_init(&new); new->interface_str = orig->interface_str; if (orig->if_context_str != NULL) { new->if_context_str = orig->if_context_str; } else { cil_context_init(&new->if_context); cil_copy_fill_context(db, orig->if_context, new->if_context); } if (orig->packet_context_str != NULL) { new->packet_context_str = orig->packet_context_str; } else { cil_context_init(&new->packet_context); cil_copy_fill_context(db, orig->packet_context, new->packet_context); } *copy = new; return SEPOL_OK; } int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_genfscon *orig = data; struct cil_genfscon *new = NULL; cil_genfscon_init(&new); new->fs_str = orig->fs_str; new->path_str = orig->path_str; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_filecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_filecon *orig = data; struct cil_filecon *new = NULL; cil_filecon_init(&new); new->path_str = orig->path_str; new->type = orig->type; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else if (orig->context != NULL) { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_nodecon *orig = data; struct cil_nodecon *new = NULL; cil_nodecon_init(&new); if (orig->addr_str != NULL) { new->addr_str = orig->addr_str; } else { cil_ipaddr_init(&new->addr); cil_copy_fill_ipaddr(orig->addr, new->addr); } if (orig->mask_str != NULL) { new->mask_str = orig->mask_str; } else { cil_ipaddr_init(&new->mask); cil_copy_fill_ipaddr(orig->mask, new->mask); } if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ibpkeycon *orig = data; struct cil_ibpkeycon *new = NULL; cil_ibpkeycon_init(&new); new->subnet_prefix_str = orig->subnet_prefix_str; new->pkey_low = orig->pkey_low; new->pkey_high = orig->pkey_high; if (orig->context_str) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_ibendportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ibendportcon *orig = data; struct cil_ibendportcon *new = NULL; cil_ibendportcon_init(&new); new->dev_name_str = orig->dev_name_str; new->port = orig->port; if (orig->context_str) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_portcon *orig = data; struct cil_portcon *new = NULL; cil_portcon_init(&new); new->proto = orig->proto; new->port_low = orig->port_low; new->port_high = orig->port_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_pirqcon *orig = data; struct cil_pirqcon *new = NULL; cil_pirqcon_init(&new); new->pirq = orig->pirq; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_iomemcon *orig = data; struct cil_iomemcon *new = NULL; cil_iomemcon_init(&new); new->iomem_low = orig->iomem_low; new->iomem_high = orig->iomem_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_ioportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ioportcon *orig = data; struct cil_ioportcon *new = NULL; cil_ioportcon_init(&new); new->ioport_low = orig->ioport_low; new->ioport_high = orig->ioport_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_pcidevicecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_pcidevicecon *orig = data; struct cil_pcidevicecon *new = NULL; cil_pcidevicecon_init(&new); new->dev = orig->dev; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_devicetreecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_devicetreecon *orig = data; struct cil_devicetreecon *new = NULL; cil_devicetreecon_init(&new); new->path = orig->path; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_fsuse(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_fsuse *orig = data; struct cil_fsuse *new = NULL; cil_fsuse_init(&new); new->type = orig->type; new->fs_str = orig->fs_str; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_expr(struct cil_db *db, struct cil_list *orig, struct cil_list **new) { struct cil_list_item *curr; if (orig == NULL) { *new = NULL; return SEPOL_OK; } cil_list_init(new, orig->flavor); cil_list_for_each(curr, orig) { switch (curr->flavor) { case CIL_LIST: { struct cil_list *sub_list; cil_copy_expr(db, curr->data, &sub_list); cil_list_append(*new, CIL_LIST, sub_list); break; } case CIL_STRING: cil_list_append(*new, CIL_STRING, curr->data); break; case CIL_DATUM: cil_list_append(*new, curr->flavor, curr->data); break; case CIL_OP: cil_list_append(*new, curr->flavor, curr->data); break; case CIL_CONS_OPERAND: cil_list_append(*new, curr->flavor, curr->data); break; default: cil_log(CIL_INFO, "Unknown flavor %d in expression being copied\n",curr->flavor); cil_list_append(*new, curr->flavor, curr->data); break; } } return SEPOL_OK; } int cil_copy_constrain(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_constrain *orig = data; struct cil_constrain *new = NULL; cil_constrain_init(&new); cil_copy_classperms_list(orig->classperms, &new->classperms); cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_validatetrans(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_validatetrans *orig = data; struct cil_validatetrans *new = NULL; cil_validatetrans_init(&new); new->class_str = orig->class_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_call(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_call *orig = data; struct cil_call *new = NULL; int rc = SEPOL_ERR; cil_call_init(&new); new->macro_str = orig->macro_str; new->macro = orig->macro; if (orig->args_tree != NULL) { cil_tree_init(&new->args_tree); rc = cil_copy_ast(db, orig->args_tree->root, new->args_tree->root); if (rc != SEPOL_OK) { goto exit; } } new->copied = orig->copied; *copy = new; return SEPOL_OK; exit: cil_destroy_call(new); return rc; } int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_macro *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_macro *new; cil_macro_init(&new); if (orig->params != NULL) { cil_copy_list(orig->params, &new->params); } *copy = new; } else { struct cil_list_item *curr_orig = NULL; struct cil_list_item *curr_new = NULL; struct cil_param *param_orig = NULL; struct cil_param *param_new = NULL; if (((struct cil_macro*)datum)->params != NULL) { curr_new = ((struct cil_macro*)datum)->params->head; } if (orig->params != NULL) { curr_orig = orig->params->head; } if (curr_orig != NULL && curr_new != NULL) { while (curr_orig != NULL) { if (curr_new == NULL) { goto exit; } param_orig = (struct cil_param*)curr_orig->data; param_new = (struct cil_param*)curr_new->data; if (param_orig->str != param_new->str) { goto exit; } else if (param_orig->flavor != param_new->flavor) { goto exit; } curr_orig = curr_orig->next; curr_new = curr_new->next; } if (curr_new != NULL) { goto exit; } } else if (!(curr_orig == NULL && curr_new == NULL)) { goto exit; } *copy = datum; } return SEPOL_OK; exit: cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n"); return SEPOL_ERR; } int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_optional *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_optional *new; cil_optional_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } void cil_copy_fill_ipaddr(struct cil_ipaddr *data, struct cil_ipaddr *new) { new->family = data->family; memcpy(&new->ip, &data->ip, sizeof(data->ip)); } int cil_copy_ipaddr(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_ipaddr *orig = data; struct cil_ipaddr *new = NULL; char * key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_ipaddr: ipaddress cannot be redefined\n"); return SEPOL_ERR; } cil_ipaddr_init(&new); cil_copy_fill_ipaddr(orig, new); *copy = new; return SEPOL_OK; } int cil_copy_condblock(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_condblock *orig = data; struct cil_condblock *new = *copy; cil_condblock_init(&new); new->flavor = orig->flavor; *copy = new; return SEPOL_OK; } int cil_copy_boolif(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_booleanif *orig = data; struct cil_booleanif *new = NULL; cil_boolif_init(&new); cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); new->preserved_tunable = orig->preserved_tunable; *copy = new; return SEPOL_OK; } int cil_copy_tunif(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_tunableif *orig = data; struct cil_tunableif *new = NULL; cil_tunif_init(&new); cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_default(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_default *orig = data; struct cil_default *new = NULL; cil_default_init(&new); new->flavor = orig->flavor; if (orig->class_strs != NULL) { cil_copy_list(orig->class_strs, &new->class_strs); } new->object = orig->object; *copy = new; return SEPOL_OK; } int cil_copy_defaultrange(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_defaultrange *orig = data; struct cil_defaultrange *new = NULL; cil_defaultrange_init(&new); if (orig->class_strs != NULL) { cil_copy_list(orig->class_strs, &new->class_strs); } new->object_range = orig->object_range; *copy = new; return SEPOL_OK; } int cil_copy_handleunknown(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_handleunknown *orig = data; struct cil_handleunknown *new = NULL; cil_handleunknown_init(&new); new->handle_unknown = orig->handle_unknown; *copy = new; return SEPOL_OK; } int cil_copy_mls(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_mls *orig = data; struct cil_mls *new = NULL; cil_mls_init(&new); new->value = orig->value; *copy = new; return SEPOL_OK; } int cil_copy_bounds(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_bounds *orig = data; struct cil_bounds *new = NULL; cil_bounds_init(&new); new->parent_str = orig->parent_str; new->child_str = orig->child_str; *copy = new; return SEPOL_OK; } int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_src_info *orig = data; struct cil_src_info *new = NULL; cil_src_info_init(&new); new->is_cil = orig->is_cil; new->path = orig->path; *copy = new; return SEPOL_OK; } int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_tree_node *parent = NULL; struct cil_tree_node *new = NULL; struct cil_db *db = NULL; struct cil_args_copy *args = NULL; struct cil_tree_node *namespace = NULL; struct cil_param *param = NULL; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; symtab_t *symtab = NULL; void *data = NULL; int (*copy_func)(struct cil_db *db, void *data, void **copy, symtab_t *symtab) = NULL; struct cil_blockinherit *blockinherit = NULL; if (orig == NULL || extra_args == NULL) { goto exit; } args = extra_args; parent = args->dest; db = args->db; switch (orig->flavor) { case CIL_BLOCK: copy_func = &cil_copy_block; break; case CIL_BLOCKABSTRACT: copy_func = &cil_copy_blockabstract; break; case CIL_BLOCKINHERIT: copy_func = &cil_copy_blockinherit; break; case CIL_POLICYCAP: copy_func = &cil_copy_policycap; break; case CIL_PERM: case CIL_MAP_PERM: copy_func = &cil_copy_perm; break; case CIL_CLASSMAPPING: copy_func = &cil_copy_classmapping; break; case CIL_CLASS: case CIL_COMMON: case CIL_MAP_CLASS: copy_func = &cil_copy_class; break; case CIL_CLASSORDER: copy_func = &cil_copy_classorder; break; case CIL_CLASSPERMISSION: copy_func = &cil_copy_classpermission; break; case CIL_CLASSPERMISSIONSET: copy_func = &cil_copy_classpermissionset; break; case CIL_CLASSCOMMON: copy_func = &cil_copy_classcommon; break; case CIL_SID: copy_func = &cil_copy_sid; break; case CIL_SIDCONTEXT: copy_func = &cil_copy_sidcontext; break; case CIL_SIDORDER: copy_func = &cil_copy_sidorder; break; case CIL_USER: copy_func = &cil_copy_user; break; case CIL_USERATTRIBUTE: copy_func = &cil_copy_userattribute; break; case CIL_USERATTRIBUTESET: copy_func = &cil_copy_userattributeset; break; case CIL_USERROLE: copy_func = &cil_copy_userrole; break; case CIL_USERLEVEL: copy_func = &cil_copy_userlevel; break; case CIL_USERRANGE: copy_func = &cil_copy_userrange; break; case CIL_USERBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_USERPREFIX: copy_func = &cil_copy_userprefix; break; case CIL_ROLE: copy_func = &cil_copy_role; break; case CIL_ROLETYPE: copy_func = &cil_copy_roletype; break; case CIL_ROLEBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_ROLEATTRIBUTE: copy_func = &cil_copy_roleattribute; break; case CIL_ROLEATTRIBUTESET: copy_func = &cil_copy_roleattributeset; break; case CIL_ROLEALLOW: copy_func = &cil_copy_roleallow; break; case CIL_TYPE: copy_func = &cil_copy_type; break; case CIL_TYPEBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_TYPEPERMISSIVE: copy_func = cil_copy_typepermissive; break; case CIL_TYPEATTRIBUTE: copy_func = &cil_copy_typeattribute; break; case CIL_TYPEATTRIBUTESET: copy_func = &cil_copy_typeattributeset; break; case CIL_EXPANDTYPEATTRIBUTE: copy_func = &cil_copy_expandtypeattribute; break; case CIL_TYPEALIAS: copy_func = &cil_copy_alias; break; case CIL_TYPEALIASACTUAL: copy_func = &cil_copy_aliasactual; break; case CIL_ROLETRANSITION: copy_func = &cil_copy_roletransition; break; case CIL_NAMETYPETRANSITION: copy_func = &cil_copy_nametypetransition; break; case CIL_RANGETRANSITION: copy_func = &cil_copy_rangetransition; break; case CIL_TUNABLE: copy_func = &cil_copy_tunable; break; case CIL_BOOL: copy_func = &cil_copy_bool; break; case CIL_AVRULE: case CIL_AVRULEX: copy_func = &cil_copy_avrule; break; case CIL_PERMISSIONX: copy_func = &cil_copy_permissionx; break; case CIL_TYPE_RULE: copy_func = &cil_copy_type_rule; break; case CIL_SENS: copy_func = &cil_copy_sens; break; case CIL_SENSALIAS: copy_func = &cil_copy_alias; break; case CIL_SENSALIASACTUAL: copy_func = &cil_copy_aliasactual; break; case CIL_CAT: copy_func = &cil_copy_cat; break; case CIL_CATALIAS: copy_func = &cil_copy_alias; break; case CIL_CATALIASACTUAL: copy_func = &cil_copy_aliasactual; break; case CIL_CATSET: copy_func = &cil_copy_catset; break; case CIL_SENSCAT: copy_func = &cil_copy_senscat; break; case CIL_CATORDER: copy_func = &cil_copy_catorder; break; case CIL_SENSITIVITYORDER: copy_func = &cil_copy_sensitivityorder; break; case CIL_LEVEL: copy_func = &cil_copy_level; break; case CIL_LEVELRANGE: copy_func = &cil_copy_levelrange; break; case CIL_CONTEXT: copy_func = &cil_copy_context; break; case CIL_NETIFCON: copy_func = &cil_copy_netifcon; break; case CIL_GENFSCON: copy_func = &cil_copy_genfscon; break; case CIL_FILECON: copy_func = &cil_copy_filecon; break; case CIL_NODECON: copy_func = &cil_copy_nodecon; break; case CIL_IBPKEYCON: copy_func = &cil_copy_ibpkeycon; break; case CIL_IBENDPORTCON: copy_func = &cil_copy_ibendportcon; break; case CIL_PORTCON: copy_func = &cil_copy_portcon; break; case CIL_PIRQCON: copy_func = &cil_copy_pirqcon; break; case CIL_IOMEMCON: copy_func = &cil_copy_iomemcon; break; case CIL_IOPORTCON: copy_func = &cil_copy_ioportcon; break; case CIL_PCIDEVICECON: copy_func = &cil_copy_pcidevicecon; break; case CIL_DEVICETREECON: copy_func = &cil_copy_devicetreecon; break; case CIL_FSUSE: copy_func = &cil_copy_fsuse; break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: copy_func = &cil_copy_constrain; break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: copy_func = &cil_copy_validatetrans; break; case CIL_CALL: copy_func = &cil_copy_call; break; case CIL_MACRO: copy_func = &cil_copy_macro; break; case CIL_NODE: copy_func = &cil_copy_node; break; case CIL_OPTIONAL: copy_func = &cil_copy_optional; break; case CIL_IPADDR: copy_func = &cil_copy_ipaddr; break; case CIL_CONDBLOCK: copy_func = &cil_copy_condblock; break; case CIL_BOOLEANIF: copy_func = &cil_copy_boolif; break; case CIL_TUNABLEIF: copy_func = &cil_copy_tunif; break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: copy_func = &cil_copy_default; break; case CIL_DEFAULTRANGE: copy_func = &cil_copy_defaultrange; break; case CIL_HANDLEUNKNOWN: copy_func = &cil_copy_handleunknown; break; case CIL_MLS: copy_func = &cil_copy_mls; break; case CIL_SRC_INFO: copy_func = &cil_copy_src_info; break; default: goto exit; } if (orig->flavor >= CIL_MIN_DECLARATIVE) { rc = cil_flavor_to_symtab_index(orig->flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_get_symtab(parent, &symtab, sym_index); if (rc != SEPOL_OK) { goto exit; } } rc = (*copy_func)(db, orig->data, &data, symtab); if (rc == SEPOL_OK) { cil_tree_node_init(&new); new->parent = parent; new->line = orig->line; new->hll_line = orig->hll_line; new->flavor = orig->flavor; new->data = data; if (orig->flavor >= CIL_MIN_DECLARATIVE) { /* Check the flavor of data if was found in the destination symtab */ if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) { cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name); cil_tree_log(NODE(data), CIL_ERR, "Note: conflicting declaration"); new->flavor = FLAVOR(data); rc = SEPOL_ERR; goto exit; } rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new); namespace = new; while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) { namespace = namespace->parent; } if (namespace->flavor == CIL_MACRO) { struct cil_macro *macro = namespace->data; struct cil_list *param_list = macro->params; if (param_list != NULL) { struct cil_list_item *item; cil_list_for_each(item, param_list) { param = item->data; if (param->flavor == new->flavor) { if (param->str == ((struct cil_symtab_datum*)new->data)->name) { cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name); cil_tree_log(namespace, CIL_ERR, "Note: macro declaration"); rc = SEPOL_ERR; goto exit; } } } } } } if (new->flavor == CIL_BLOCKINHERIT) { blockinherit = new->data; // if a blockinherit statement is copied before blockinherit are // resolved (like in an in-statement), the block will not have been // resolved yet, so there's nothing to append yet. This is fine, // the copied blockinherit statement will be handled later, as if // it wasn't in an in-statement if (blockinherit->block != NULL) { cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new); } } if (parent->cl_head == NULL) { parent->cl_head = new; parent->cl_tail = new; } else { parent->cl_tail->next = new; parent->cl_tail = new; } if (orig->cl_head != NULL) { args->dest = new; } } else { goto exit; } return SEPOL_OK; exit: cil_tree_node_destroy(&new); return rc; } int __cil_copy_last_child_helper(__attribute__((unused)) struct cil_tree_node *orig, void *extra_args) { struct cil_tree_node *node = NULL; struct cil_args_copy *args = NULL; args = extra_args; node = args->dest; if (node->flavor != CIL_ROOT) { args->dest = node->parent; } return SEPOL_OK; } // dest is the parent node to copy into // if the copy is for a call to a macro, dest should be a pointer to the call int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_node *dest) { int rc = SEPOL_ERR; struct cil_args_copy extra_args; extra_args.dest = dest; extra_args.db = db; rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); goto exit; } return SEPOL_OK; exit: return rc; } libsepol/cil/src/cil_copy_ast.h0100644 0000000 0000000 00000020652 13756670064 015620 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_COPY_H_ #define CIL_COPY_H_ #include "cil_internal.h" #include "cil_tree.h" #include "cil_symtab.h" void cil_copy_list(struct cil_list *orig, struct cil_list **copy); int cil_copy_expr(struct cil_db *db, struct cil_list *orig, struct cil_list **new); int cil_copy_block(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_blockabstract(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_blockinherit(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_perm(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_class(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_classorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_classmapping(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_permset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_classperms(struct cil_classperms *orig, struct cil_classperms **new); void cil_copy_classperms_set(struct cil_classperms_set *orig, struct cil_classperms_set **new); void cil_copy_classperms_list(struct cil_list *orig, struct cil_list **new); int cil_copy_classpermission(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab); int cil_copy_common(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_classcommon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sid(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sidorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrole(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userbounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userprefix(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_role(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roletype(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_rolebounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleallow(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_type(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typebounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typepermissive(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typeattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typeattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typealias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_nametypetransition(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_rangetransition(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_bool(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_avrule(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_type_rule(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sens(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sensalias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_cat(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_catalias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_catset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_senscat(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_catorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sensitivityorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new); int cil_copy_level(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_levelrange(struct cil_db *db, struct cil_levelrange *orig, struct cil_levelrange *new); int cil_copy_levelrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_context(struct cil_db *db, struct cil_context *orig, struct cil_context *new); int cil_copy_context(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_netifcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_filecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_portcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ioportcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_pcidevicecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_fsuse(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_exrp(struct cil_db *db, struct cil_list *orig, struct cil_list **new); int cil_copy_constrain(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_validatetrans(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_call(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_optional(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_ipaddr(struct cil_ipaddr *orig, struct cil_ipaddr *new); int cil_copy_ipaddr(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_boolif(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_node *dest); #endif libsepol/cil/src/cil_find.c0100644 0000000 0000000 00000027330 13756670064 014712 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_list.h" #include "cil_log.h" #include "cil_symtab.h" struct cil_args_find { enum cil_flavor flavor; void *target; struct cil_list *matching; int match_self; }; static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) { enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; if (t1->value == t2->value) { return CIL_TRUE; } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a = (struct cil_typeattribute *)d1; struct cil_type *t = (struct cil_type *)d2; if (ebitmap_get_bit(a->types, t->value)) { return CIL_TRUE; } } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_type *t = (struct cil_type *)d1; struct cil_typeattribute *a = (struct cil_typeattribute *)d2; if (ebitmap_get_bit(a->types, t->value)) { return CIL_TRUE; } } else { /* Both are attributes */ struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; if (d1 == d2) { return CIL_TRUE; } else if (ebitmap_match_any(a1->types, a2->types)) { return CIL_TRUE; } } return CIL_FALSE; } static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) { int rc = SEPOL_OK; enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; if (t1->value == t2->value) { ebitmap_set_bit(matches, t1->value, 1); } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a = (struct cil_typeattribute *)d1; struct cil_type *t = (struct cil_type *)d2; if (ebitmap_get_bit(a->types, t->value)) { ebitmap_set_bit(matches, t->value, 1); } } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_type *t = (struct cil_type *)d1; struct cil_typeattribute *a = (struct cil_typeattribute *)d2; if (ebitmap_get_bit(a->types, t->value)) { ebitmap_set_bit(matches, t->value, 1); } } else { /* Both are attributes */ struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; rc = ebitmap_and(matches, a1->types, a2->types); } return rc; } /* s1 is the src type that is matched with a self * s2, and t2 are the source and type of the other rule */ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) { int rc; struct cil_tree_node *n1 = s1->nodes->head->data; if (n1->flavor != CIL_TYPEATTRIBUTE) { rc = cil_type_match_any(s1, t2); } else { struct cil_typeattribute *a = (struct cil_typeattribute *)s1; ebitmap_t map; ebitmap_init(&map); rc = cil_type_matches(&map, s2, t2); if (rc < 0) { ebitmap_destroy(&map); goto exit; } if (map.node == NULL) { rc = CIL_FALSE; goto exit; } rc = ebitmap_match_any(&map, a->types); ebitmap_destroy(&map); } exit: return rc; } static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2) { struct cil_class *c1 = cp1->class; struct cil_class *c2 = cp2->class; struct cil_list_item *i1, *i2; if (&c1->datum != &c2->datum) return CIL_FALSE; cil_list_for_each(i1, cp1->perms) { struct cil_perm *p1 = i1->data; cil_list_for_each(i2, cp2->perms) { struct cil_perm *p2 = i2->data; if (&p1->datum == &p2->datum) return CIL_TRUE; } } return CIL_FALSE; } static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2) { int rc; struct cil_list_item *curr; cil_list_for_each(curr, cpl2) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = cil_classperms_match_any(cp1, cp); if (rc == CIL_TRUE) return CIL_TRUE; } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __cil_classperms_list_match_any(cp1, cmp->classperms); if (rc == CIL_TRUE) return CIL_TRUE; } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_classperms_list_match_any(cp1, cp->classperms); if (rc == CIL_TRUE) return CIL_TRUE; } } return CIL_FALSE; } static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2) { int rc; struct cil_list_item *curr; cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __cil_classperms_list_match_any(cp, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = cil_classperms_list_match_any(cmp->classperms, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = cil_classperms_list_match_any(cp->classperms, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } } return CIL_FALSE; } static void __add_classes_from_classperms_list(struct cil_list *classperms, struct cil_list *class_list) { struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_list_append(class_list, CIL_CLASS, cp->class); } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; __add_classes_from_classperms_list(cmp->classperms, class_list); } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; __add_classes_from_classperms_list(cp->classperms, class_list); } } } static int __add_classes_from_map_perms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_list *class_list = args; struct cil_perm *cmp = (struct cil_perm *)d; __add_classes_from_classperms_list(cmp->classperms, class_list); return SEPOL_OK; } struct cil_list *cil_expand_class(struct cil_class *class) { struct cil_list *class_list; cil_list_init(&class_list, CIL_CLASS); if (FLAVOR(class) == CIL_CLASS) { cil_list_append(class_list, CIL_CLASS, class); } else { /* MAP */ cil_symtab_map(&class->perms, __add_classes_from_map_perms, class_list); } return class_list; } static int cil_permissionx_match_any(struct cil_permissionx *px1, struct cil_permissionx *px2) { int rc = CIL_FALSE; struct cil_list *cl1 = NULL; struct cil_list *cl2 = NULL; if (px1->kind != px2->kind) goto exit; if (!ebitmap_match_any(px1->perms, px2->perms)) goto exit; cl1 = cil_expand_class(px1->obj); cl2 = cil_expand_class(px2->obj); if (!cil_list_match_any(cl1, cl2)) goto exit; rc = CIL_TRUE; exit: cil_list_destroy(&cl1, CIL_FALSE); cil_list_destroy(&cl2, CIL_FALSE); return rc; } int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrule *avrule, struct cil_avrule *target, struct cil_list *matching, int match_self) { int rc = SEPOL_OK; struct cil_symtab_datum *s1 = avrule->src; struct cil_symtab_datum *t1 = avrule->tgt; struct cil_symtab_datum *s2 = target->src; struct cil_symtab_datum *t2 = target->tgt; if (match_self != CIL_TRUE && avrule == target) goto exit; if (avrule->rule_kind != target->rule_kind) goto exit; if (avrule->is_extended != target->is_extended) goto exit; if (!cil_type_match_any(s1, s2)) goto exit; if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) { if (!cil_type_match_any(t1, t2)) goto exit; } else { if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) { /* The earlier check whether s1 and s2 matches is all that is needed */ } else if (t1->fqn == CIL_KEY_SELF) { rc = cil_self_match_any(s1, s2, t2); if (rc < 0) { goto exit; } else if (rc == CIL_FALSE) { rc = SEPOL_OK; goto exit; } } else if (t2->fqn == CIL_KEY_SELF) { rc = cil_self_match_any(s2, s1, t1); if (rc < 0) { goto exit; } else if (rc == CIL_FALSE) { rc = SEPOL_OK; goto exit; } } } if (!target->is_extended) { if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) { cil_list_append(matching, CIL_NODE, node); } } else { if (cil_permissionx_match_any(avrule->perms.x.permx, target->perms.x.permx)) { cil_list_append(matching, CIL_NODE, node); } } rc = SEPOL_OK; exit: return rc; } static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_OK; struct cil_args_find *args = extra_args; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; goto exit; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; goto exit; } else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) { if (node->flavor == args->flavor) { rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self); } } exit: return rc; } int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self) { int rc; struct cil_args_find args; args.flavor = flavor; args.target = target; args.matching = matching; args.match_self = match_self; rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args); if (rc) { cil_log(CIL_ERR, "An error occurred while searching for avrule in AST\n"); } return rc; } libsepol/cil/src/cil_find.h0100644 0000000 0000000 00000003616 13756670064 014720 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "cil_flavor.h" #include "cil_tree.h" #include "cil_list.h" #ifndef CIL_FIND_H_ #define CIL_FIND_H_ int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self); struct cil_list *cil_expand_class(struct cil_class *class); #endif libsepol/cil/src/cil_flavor.h0100644 0000000 0000000 00000010444 13756670064 015266 0ustar000000000 0000000 /* * Copyright 2013 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_FLAVOR_H_ #define CIL_FLAVOR_H_ /* Tree/list node types */ #define CIL_MIN_OP_OPERANDS 1000 #define CIL_MIN_DECLARATIVE 2000 enum cil_flavor { CIL_NONE = 0, CIL_ROOT, CIL_NODE, CIL_STRING, CIL_DATUM, CIL_LIST, CIL_LIST_ITEM, CIL_PARAM, CIL_ARGS, CIL_BLOCKINHERIT, CIL_BLOCKABSTRACT, CIL_IN, CIL_CALL, CIL_BOOLEANIF, CIL_TUNABLEIF, CIL_CONDBLOCK, CIL_CONDTRUE, CIL_CONDFALSE, CIL_CLASSORDER, CIL_CLASSCOMMON, CIL_CLASSMAPPING, CIL_CLASSPERMS, CIL_CLASSPERMS_SET, CIL_CLASSPERMISSIONSET, CIL_USERPREFIX, CIL_USERROLE, CIL_USERATTRIBUTESET, CIL_USERLEVEL, CIL_USERRANGE, CIL_USERBOUNDS, CIL_SELINUXUSER, CIL_SELINUXUSERDEFAULT, CIL_ROLEATTRIBUTESET, CIL_ROLETYPE, CIL_ROLEBOUNDS, CIL_TYPEATTRIBUTESET, CIL_EXPANDTYPEATTRIBUTE, CIL_TYPEALIASACTUAL, CIL_TYPEBOUNDS, CIL_TYPEPERMISSIVE, CIL_SENSALIASACTUAL, CIL_SENSITIVITYORDER, CIL_SENSCAT, CIL_CATALIASACTUAL, CIL_CATORDER, CIL_SIDORDER, CIL_ROLEALLOW, CIL_AVRULE, CIL_AVRULEX, CIL_ROLETRANSITION, CIL_TYPE_RULE, CIL_NAMETYPETRANSITION, CIL_RANGETRANSITION, CIL_CONSTRAIN, CIL_MLSCONSTRAIN, CIL_VALIDATETRANS, CIL_MLSVALIDATETRANS, CIL_SIDCONTEXT, CIL_FSUSE, CIL_FILECON, CIL_PORTCON, CIL_NODECON, CIL_GENFSCON, CIL_NETIFCON, CIL_PIRQCON, CIL_IOMEMCON, CIL_IOPORTCON, CIL_PCIDEVICECON, CIL_DEVICETREECON, CIL_DEFAULTUSER, CIL_DEFAULTROLE, CIL_DEFAULTTYPE, CIL_DEFAULTRANGE, CIL_HANDLEUNKNOWN, CIL_MLS, CIL_SRC_INFO, CIL_IBPKEYCON, CIL_IBENDPORTCON, /* * boolean constraint set catset * dom X * domby X * incomp X * eq X X * ne X X * and X X X X * not X X X X * or X X X X * xor X X X * all X X * range X */ CIL_OP = CIL_MIN_OP_OPERANDS, CIL_ALL, CIL_AND, CIL_OR, CIL_XOR, CIL_NOT, CIL_EQ, CIL_NEQ, CIL_RANGE, CIL_CONS_DOM, CIL_CONS_DOMBY, CIL_CONS_INCOMP, CIL_CONS_OPERAND, CIL_CONS_U1, CIL_CONS_U2, CIL_CONS_U3, CIL_CONS_T1, CIL_CONS_T2, CIL_CONS_T3, CIL_CONS_R1, CIL_CONS_R2, CIL_CONS_R3, CIL_CONS_L1, CIL_CONS_L2, CIL_CONS_H1, CIL_CONS_H2, CIL_BLOCK = CIL_MIN_DECLARATIVE, CIL_MACRO, CIL_OPTIONAL, CIL_BOOL, CIL_TUNABLE, CIL_PERM, CIL_MAP_PERM, CIL_COMMON, CIL_CLASS, CIL_MAP_CLASS, CIL_CLASSPERMISSION, CIL_USER, CIL_USERATTRIBUTE, CIL_ROLE, CIL_ROLEATTRIBUTE, CIL_TYPE, CIL_TYPEATTRIBUTE, CIL_TYPEALIAS, CIL_SENS, CIL_SENSALIAS, CIL_CAT, CIL_CATSET, CIL_CATALIAS, CIL_LEVEL, CIL_LEVELRANGE, CIL_SID, CIL_NAME, CIL_CONTEXT, CIL_IPADDR, CIL_POLICYCAP, CIL_PERMISSIONX }; #endif /* CIL_FLAVOR_H_ */ libsepol/cil/src/cil_fqn.c0100644 0000000 0000000 00000010404 13756670064 014550 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include "cil_internal.h" #include "cil_log.h" #include "cil_strpool.h" #include "cil_symtab.h" struct cil_fqn_args { char prefix[CIL_MAX_NAME_LENGTH]; int len; struct cil_tree_node *node; }; static int __cil_fqn_qualify_decls(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_fqn_args *fqn_args = args; struct cil_symtab_datum *datum = (struct cil_symtab_datum *)d; int newlen; char prefix[CIL_MAX_NAME_LENGTH]; int rc = SEPOL_OK; if (fqn_args->len == 0) { goto exit; } newlen = fqn_args->len + strlen(datum->name); if (newlen >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_INFO, "Fully qualified name for %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } strcpy(prefix, fqn_args->prefix); strcat(prefix, datum->name); datum->fqn = cil_strpool_add(prefix); exit: return rc; } static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_fqn_args *fqn_args = args; struct cil_fqn_args child_args; struct cil_block *block = (struct cil_block *)d; struct cil_symtab_datum *datum = (struct cil_symtab_datum *)block; struct cil_tree_node *node = NODE(datum); int i; int rc = SEPOL_OK; if (node->flavor != CIL_BLOCK) { goto exit; } int newlen = fqn_args->len + strlen(datum->name) + 1; if (newlen >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } child_args.node = node; child_args.len = newlen; strcpy(child_args.prefix, fqn_args->prefix); strcat(child_args.prefix, datum->name); strcat(child_args.prefix, "."); for (i=1; isymtab[i]), __cil_fqn_qualify_decls, &child_args); if (rc != SEPOL_OK) { goto exit; } break; } } rc = cil_symtab_map(&(block->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &child_args); exit: if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR,"Problem qualifying names in block"); } return rc; } int cil_fqn_qualify(struct cil_tree_node *root_node) { struct cil_root *root = root_node->data; struct cil_fqn_args fqn_args; fqn_args.prefix[0] = '\0'; fqn_args.len = 0; fqn_args.node = root_node; return cil_symtab_map(&(root->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &fqn_args); } libsepol/cil/src/cil_fqn.h0100644 0000000 0000000 00000003363 13756670064 014563 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_FQN_H_ #define CIL_FQN_H_ #include "cil_internal.h" #include "cil_tree.h" int cil_fqn_qualify(struct cil_tree_node *root_node); #endif /* CIL_FQN_H_ */ libsepol/cil/src/cil_internal.h0100644 0000000 0000000 00000062703 13756670065 015617 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_INTERNAL_H_ #define CIL_INTERNAL_H_ #include #include #include #include #include #include #include #include #include "cil_flavor.h" #include "cil_tree.h" #include "cil_symtab.h" #include "cil_mem.h" #define CIL_MAX_NAME_LENGTH 2048 enum cil_pass { CIL_PASS_INIT = 0, CIL_PASS_TIF, CIL_PASS_IN, CIL_PASS_BLKIN_LINK, CIL_PASS_BLKIN_COPY, CIL_PASS_BLKABS, CIL_PASS_MACRO, CIL_PASS_CALL1, CIL_PASS_CALL2, CIL_PASS_ALIAS1, CIL_PASS_ALIAS2, CIL_PASS_MISC1, CIL_PASS_MLS, CIL_PASS_MISC2, CIL_PASS_MISC3, CIL_PASS_NUM }; /* Keywords */ char *CIL_KEY_CONS_T1; char *CIL_KEY_CONS_T2; char *CIL_KEY_CONS_T3; char *CIL_KEY_CONS_R1; char *CIL_KEY_CONS_R2; char *CIL_KEY_CONS_R3; char *CIL_KEY_CONS_U1; char *CIL_KEY_CONS_U2; char *CIL_KEY_CONS_U3; char *CIL_KEY_CONS_L1; char *CIL_KEY_CONS_L2; char *CIL_KEY_CONS_H1; char *CIL_KEY_CONS_H2; char *CIL_KEY_AND; char *CIL_KEY_OR; char *CIL_KEY_NOT; char *CIL_KEY_EQ; char *CIL_KEY_NEQ; char *CIL_KEY_CONS_DOM; char *CIL_KEY_CONS_DOMBY; char *CIL_KEY_CONS_INCOMP; char *CIL_KEY_CONDTRUE; char *CIL_KEY_CONDFALSE; char *CIL_KEY_SELF; char *CIL_KEY_OBJECT_R; char *CIL_KEY_STAR; char *CIL_KEY_TCP; char *CIL_KEY_UDP; char *CIL_KEY_DCCP; char *CIL_KEY_SCTP; char *CIL_KEY_AUDITALLOW; char *CIL_KEY_TUNABLEIF; char *CIL_KEY_ALLOW; char *CIL_KEY_DONTAUDIT; char *CIL_KEY_TYPETRANSITION; char *CIL_KEY_TYPECHANGE; char *CIL_KEY_CALL; char *CIL_KEY_TUNABLE; char *CIL_KEY_XOR; char *CIL_KEY_ALL; char *CIL_KEY_RANGE; char *CIL_KEY_GLOB; char *CIL_KEY_FILE; char *CIL_KEY_DIR; char *CIL_KEY_CHAR; char *CIL_KEY_BLOCK; char *CIL_KEY_SOCKET; char *CIL_KEY_PIPE; char *CIL_KEY_SYMLINK; char *CIL_KEY_ANY; char *CIL_KEY_XATTR; char *CIL_KEY_TASK; char *CIL_KEY_TRANS; char *CIL_KEY_TYPE; char *CIL_KEY_ROLE; char *CIL_KEY_USER; char *CIL_KEY_USERATTRIBUTE; char *CIL_KEY_USERATTRIBUTESET; char *CIL_KEY_SENSITIVITY; char *CIL_KEY_CATEGORY; char *CIL_KEY_CATSET; char *CIL_KEY_LEVEL; char *CIL_KEY_LEVELRANGE; char *CIL_KEY_CLASS; char *CIL_KEY_IPADDR; char *CIL_KEY_MAP_CLASS; char *CIL_KEY_CLASSPERMISSION; char *CIL_KEY_BOOL; char *CIL_KEY_STRING; char *CIL_KEY_NAME; char *CIL_KEY_SOURCE; char *CIL_KEY_TARGET; char *CIL_KEY_LOW; char *CIL_KEY_HIGH; char *CIL_KEY_LOW_HIGH; char *CIL_KEY_HANDLEUNKNOWN; char *CIL_KEY_HANDLEUNKNOWN_ALLOW; char *CIL_KEY_HANDLEUNKNOWN_DENY; char *CIL_KEY_HANDLEUNKNOWN_REJECT; char *CIL_KEY_MACRO; char *CIL_KEY_IN; char *CIL_KEY_MLS; char *CIL_KEY_DEFAULTRANGE; char *CIL_KEY_BLOCKINHERIT; char *CIL_KEY_BLOCKABSTRACT; char *CIL_KEY_CLASSORDER; char *CIL_KEY_CLASSMAPPING; char *CIL_KEY_CLASSPERMISSIONSET; char *CIL_KEY_COMMON; char *CIL_KEY_CLASSCOMMON; char *CIL_KEY_SID; char *CIL_KEY_SIDCONTEXT; char *CIL_KEY_SIDORDER; char *CIL_KEY_USERLEVEL; char *CIL_KEY_USERRANGE; char *CIL_KEY_USERBOUNDS; char *CIL_KEY_USERPREFIX; char *CIL_KEY_SELINUXUSER; char *CIL_KEY_SELINUXUSERDEFAULT; char *CIL_KEY_TYPEATTRIBUTE; char *CIL_KEY_TYPEATTRIBUTESET; char *CIL_KEY_EXPANDTYPEATTRIBUTE; char *CIL_KEY_TYPEALIAS; char *CIL_KEY_TYPEALIASACTUAL; char *CIL_KEY_TYPEBOUNDS; char *CIL_KEY_TYPEPERMISSIVE; char *CIL_KEY_RANGETRANSITION; char *CIL_KEY_USERROLE; char *CIL_KEY_ROLETYPE; char *CIL_KEY_ROLETRANSITION; char *CIL_KEY_ROLEALLOW; char *CIL_KEY_ROLEATTRIBUTE; char *CIL_KEY_ROLEATTRIBUTESET; char *CIL_KEY_ROLEBOUNDS; char *CIL_KEY_BOOLEANIF; char *CIL_KEY_NEVERALLOW; char *CIL_KEY_TYPEMEMBER; char *CIL_KEY_SENSALIAS; char *CIL_KEY_SENSALIASACTUAL; char *CIL_KEY_CATALIAS; char *CIL_KEY_CATALIASACTUAL; char *CIL_KEY_CATORDER; char *CIL_KEY_SENSITIVITYORDER; char *CIL_KEY_SENSCAT; char *CIL_KEY_CONSTRAIN; char *CIL_KEY_MLSCONSTRAIN; char *CIL_KEY_VALIDATETRANS; char *CIL_KEY_MLSVALIDATETRANS; char *CIL_KEY_CONTEXT; char *CIL_KEY_FILECON; char *CIL_KEY_IBPKEYCON; char *CIL_KEY_IBENDPORTCON; char *CIL_KEY_PORTCON; char *CIL_KEY_NODECON; char *CIL_KEY_GENFSCON; char *CIL_KEY_NETIFCON; char *CIL_KEY_PIRQCON; char *CIL_KEY_IOMEMCON; char *CIL_KEY_IOPORTCON; char *CIL_KEY_PCIDEVICECON; char *CIL_KEY_DEVICETREECON; char *CIL_KEY_FSUSE; char *CIL_KEY_POLICYCAP; char *CIL_KEY_OPTIONAL; char *CIL_KEY_DEFAULTUSER; char *CIL_KEY_DEFAULTROLE; char *CIL_KEY_DEFAULTTYPE; char *CIL_KEY_ROOT; char *CIL_KEY_NODE; char *CIL_KEY_PERM; char *CIL_KEY_ALLOWX; char *CIL_KEY_AUDITALLOWX; char *CIL_KEY_DONTAUDITX; char *CIL_KEY_NEVERALLOWX; char *CIL_KEY_PERMISSIONX; char *CIL_KEY_IOCTL; char *CIL_KEY_UNORDERED; char *CIL_KEY_SRC_INFO; char *CIL_KEY_SRC_CIL; char *CIL_KEY_SRC_HLL; /* Symbol Table Array Indices */ enum cil_sym_index { CIL_SYM_BLOCKS = 0, CIL_SYM_USERS, CIL_SYM_ROLES, CIL_SYM_TYPES, CIL_SYM_COMMONS, CIL_SYM_CLASSES, CIL_SYM_CLASSPERMSETS, CIL_SYM_BOOLS, CIL_SYM_TUNABLES, CIL_SYM_SENS, CIL_SYM_CATS, CIL_SYM_SIDS, CIL_SYM_CONTEXTS, CIL_SYM_LEVELS, CIL_SYM_LEVELRANGES, CIL_SYM_POLICYCAPS, CIL_SYM_IPADDRS, CIL_SYM_NAMES, CIL_SYM_PERMX, CIL_SYM_NUM, CIL_SYM_UNKNOWN, CIL_SYM_PERMS // Special case for permissions. This symtab is not included in arrays }; enum cil_sym_array { CIL_SYM_ARRAY_ROOT = 0, CIL_SYM_ARRAY_BLOCK, CIL_SYM_ARRAY_IN, CIL_SYM_ARRAY_MACRO, CIL_SYM_ARRAY_CONDBLOCK, CIL_SYM_ARRAY_NUM }; extern int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM]; #define CIL_CLASS_SYM_SIZE 256 #define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8) struct cil_db { struct cil_tree *parse; struct cil_tree *ast; struct cil_type *selftype; struct cil_list *sidorder; struct cil_list *classorder; struct cil_list *catorder; struct cil_list *sensitivityorder; struct cil_sort *netifcon; struct cil_sort *genfscon; struct cil_sort *filecon; struct cil_sort *nodecon; struct cil_sort *ibpkeycon; struct cil_sort *ibendportcon; struct cil_sort *portcon; struct cil_sort *pirqcon; struct cil_sort *iomemcon; struct cil_sort *ioportcon; struct cil_sort *pcidevicecon; struct cil_sort *devicetreecon; struct cil_sort *fsuse; struct cil_list *userprefixes; struct cil_list *selinuxusers; struct cil_list *names; int num_types_and_attrs; int num_classes; int num_cats; int num_types; int num_roles; int num_users; struct cil_type **val_to_type; struct cil_role **val_to_role; struct cil_user **val_to_user; int disable_dontaudit; int disable_neverallow; int attrs_expand_generated; unsigned attrs_expand_size; int preserve_tunables; int handle_unknown; int mls; int multiple_decls; int target_platform; int policy_version; }; struct cil_root { symtab_t symtab[CIL_SYM_NUM]; }; struct cil_sort { enum cil_flavor flavor; uint32_t count; uint32_t index; void **array; }; struct cil_block { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; uint16_t is_abstract; struct cil_list *bi_nodes; }; struct cil_blockinherit { char *block_str; struct cil_block *block; }; struct cil_blockabstract { char *block_str; }; struct cil_in { symtab_t symtab[CIL_SYM_NUM]; char *block_str; }; struct cil_optional { struct cil_symtab_datum datum; int enabled; }; struct cil_perm { struct cil_symtab_datum datum; unsigned int value; struct cil_list *classperms; /* Only used for map perms */ }; struct cil_class { struct cil_symtab_datum datum; symtab_t perms; unsigned int num_perms; struct cil_class *common; /* Only used for kernel class */ uint32_t ordered; /* Only used for kernel class */ }; struct cil_classorder { struct cil_list *class_list_str; }; struct cil_classperms_set { char *set_str; struct cil_classpermission *set; }; struct cil_classperms { char *class_str; struct cil_class *class; struct cil_list *perm_strs; struct cil_list *perms; }; struct cil_classpermission { struct cil_symtab_datum datum; struct cil_list *classperms; }; struct cil_classpermissionset { char *set_str; struct cil_list *classperms; }; struct cil_classmapping { char *map_class_str; char *map_perm_str; struct cil_list *classperms; }; struct cil_classcommon { char *class_str; char *common_str; }; struct cil_alias { struct cil_symtab_datum datum; void *actual; }; struct cil_aliasactual { char *alias_str; char *actual_str; }; struct cil_sid { struct cil_symtab_datum datum; struct cil_context *context; uint32_t ordered; }; struct cil_sidcontext { char *sid_str; char *context_str; struct cil_context *context; }; struct cil_sidorder { struct cil_list *sid_list_str; }; struct cil_user { struct cil_symtab_datum datum; struct cil_user *bounds; ebitmap_t *roles; struct cil_level *dftlevel; struct cil_levelrange *range; int value; }; struct cil_userattribute { struct cil_symtab_datum datum; struct cil_list *expr_list; ebitmap_t *users; }; struct cil_userattributeset { char *attr_str; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_userrole { char *user_str; void *user; char *role_str; void *role; }; struct cil_userlevel { char *user_str; char *level_str; struct cil_level *level; }; struct cil_userrange { char *user_str; char *range_str; struct cil_levelrange *range; }; struct cil_userprefix { char *user_str; struct cil_user *user; char *prefix_str; }; struct cil_selinuxuser { char *name_str; char *user_str; struct cil_user *user; char *range_str; struct cil_levelrange *range; }; struct cil_role { struct cil_symtab_datum datum; struct cil_role *bounds; ebitmap_t *types; int value; }; struct cil_roleattribute { struct cil_symtab_datum datum; struct cil_list *expr_list; ebitmap_t *roles; }; struct cil_roleattributeset { char *attr_str; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_roletype { char *role_str; void *role; /* role or attribute */ char *type_str; void *type; /* type, alias, or attribute */ }; struct cil_type { struct cil_symtab_datum datum; struct cil_type *bounds; int value; }; #define CIL_ATTR_AVRULE (1 << 0) #define CIL_ATTR_NEVERALLOW (1 << 1) #define CIL_ATTR_CONSTRAINT (1 << 2) #define CIL_ATTR_EXPAND_TRUE (1 << 3) #define CIL_ATTR_EXPAND_FALSE (1 << 4) struct cil_typeattribute { struct cil_symtab_datum datum; struct cil_list *expr_list; ebitmap_t *types; int used; // whether or not this attribute was used in a binary policy rule int keep; }; struct cil_typeattributeset { char *attr_str; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_expandtypeattribute { struct cil_list *attr_strs; struct cil_list *attr_datums; int expand; }; struct cil_typepermissive { char *type_str; void *type; /* type or alias */ }; struct cil_name { struct cil_symtab_datum datum; char *name_str; }; struct cil_nametypetransition { char *src_str; void *src; /* type, alias, or attribute */ char *tgt_str; void *tgt; /* type, alias, or attribute */ char *obj_str; struct cil_class *obj; char *name_str; struct cil_name *name; char *result_str; void *result; /* type or alias */ }; struct cil_rangetransition { char *src_str; void *src; /* type, alias, or attribute */ char *exec_str; void *exec; /* type, alias, or attribute */ char *obj_str; struct cil_class *obj; char *range_str; struct cil_levelrange *range; }; struct cil_bool { struct cil_symtab_datum datum; uint16_t value; }; struct cil_tunable { struct cil_symtab_datum datum; uint16_t value; }; #define CIL_AVRULE_ALLOWED 1 #define CIL_AVRULE_AUDITALLOW 2 #define CIL_AVRULE_DONTAUDIT 8 #define CIL_AVRULE_NEVERALLOW 128 #define CIL_AVRULE_AV (AVRULE_ALLOWED | AVRULE_AUDITALLOW | AVRULE_DONTAUDIT | AVRULE_NEVERALLOW) struct cil_avrule { int is_extended; uint32_t rule_kind; char *src_str; void *src; /* type, alias, or attribute */ char *tgt_str; void *tgt; /* type, alias, or attribute */ union { struct cil_list *classperms; struct { char *permx_str; struct cil_permissionx *permx; } x; } perms; }; #define CIL_PERMX_KIND_IOCTL 1 struct cil_permissionx { struct cil_symtab_datum datum; uint32_t kind; char *obj_str; struct cil_class *obj; struct cil_list *expr_str; ebitmap_t *perms; }; #define CIL_TYPE_TRANSITION 16 #define CIL_TYPE_MEMBER 32 #define CIL_TYPE_CHANGE 64 #define CIL_AVRULE_TYPE (AVRULE_TRANSITION | AVRULE_MEMBER | AVRULE_CHANGE) struct cil_type_rule { uint32_t rule_kind; char *src_str; void *src; /* type, alias, or attribute */ char *tgt_str; void *tgt; /* type, alias, or attribute */ char *obj_str; struct cil_class *obj; char *result_str; void *result; /* type or alias */ }; struct cil_roletransition { char *src_str; struct cil_role *src; char *tgt_str; void *tgt; /* type, alias, or attribute */ char *obj_str; struct cil_class *obj; char *result_str; struct cil_role *result; }; struct cil_roleallow { char *src_str; void *src; /* role or attribute */ char *tgt_str; void *tgt; /* role or attribute */ }; struct cil_sens { struct cil_symtab_datum datum; struct cil_list *cats_list; uint32_t ordered; }; struct cil_sensorder { struct cil_list *sens_list_str; }; struct cil_cat { struct cil_symtab_datum datum; uint32_t ordered; int value; }; struct cil_cats { uint32_t evaluated; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_catset { struct cil_symtab_datum datum; struct cil_cats *cats; }; struct cil_catorder { struct cil_list *cat_list_str; }; struct cil_senscat { char *sens_str; struct cil_cats *cats; }; struct cil_level { struct cil_symtab_datum datum; char *sens_str; struct cil_sens *sens; struct cil_cats *cats; }; struct cil_levelrange { struct cil_symtab_datum datum; char *low_str; struct cil_level *low; char *high_str; struct cil_level *high; }; struct cil_context { struct cil_symtab_datum datum; char *user_str; struct cil_user *user; char *role_str; struct cil_role *role; char *type_str; void *type; /* type or alias */ char *range_str; struct cil_levelrange *range; }; enum cil_filecon_types { CIL_FILECON_FILE = 1, CIL_FILECON_DIR, CIL_FILECON_CHAR, CIL_FILECON_BLOCK, CIL_FILECON_SOCKET, CIL_FILECON_PIPE, CIL_FILECON_SYMLINK, CIL_FILECON_ANY }; struct cil_filecon { char *path_str; enum cil_filecon_types type; char *context_str; struct cil_context *context; }; enum cil_protocol { CIL_PROTOCOL_UDP = 1, CIL_PROTOCOL_TCP, CIL_PROTOCOL_DCCP, CIL_PROTOCOL_SCTP }; struct cil_ibpkeycon { char *subnet_prefix_str; uint32_t pkey_low; uint32_t pkey_high; char *context_str; struct cil_context *context; }; struct cil_portcon { enum cil_protocol proto; uint32_t port_low; uint32_t port_high; char *context_str; struct cil_context *context; }; struct cil_nodecon { char *addr_str; struct cil_ipaddr *addr; char *mask_str; struct cil_ipaddr *mask; char *context_str; struct cil_context *context; }; struct cil_ipaddr { struct cil_symtab_datum datum; int family; union { struct in_addr v4; struct in6_addr v6; } ip; }; struct cil_genfscon { char *fs_str; char *path_str; char *context_str; struct cil_context *context; }; struct cil_netifcon { char *interface_str; char *if_context_str; struct cil_context *if_context; char *packet_context_str; struct cil_context *packet_context; char *context_str; }; struct cil_ibendportcon { char *dev_name_str; uint32_t port; char *context_str; struct cil_context *context; }; struct cil_pirqcon { uint32_t pirq; char *context_str; struct cil_context *context; }; struct cil_iomemcon { uint64_t iomem_low; uint64_t iomem_high; char *context_str; struct cil_context *context; }; struct cil_ioportcon { uint32_t ioport_low; uint32_t ioport_high; char *context_str; struct cil_context *context; }; struct cil_pcidevicecon { uint32_t dev; char *context_str; struct cil_context *context; }; struct cil_devicetreecon { char *path; char *context_str; struct cil_context *context; }; /* Ensure that CIL uses the same values as sepol services.h */ enum cil_fsuse_types { CIL_FSUSE_XATTR = SECURITY_FS_USE_XATTR, CIL_FSUSE_TASK = SECURITY_FS_USE_TASK, CIL_FSUSE_TRANS = SECURITY_FS_USE_TRANS }; struct cil_fsuse { enum cil_fsuse_types type; char *fs_str; char *context_str; struct cil_context *context; }; #define CIL_MLS_LEVELS "l1 l2 h1 h2" #define CIL_CONSTRAIN_KEYS "t1 t2 r1 r2 u1 u2" #define CIL_MLSCONSTRAIN_KEYS CIL_MLS_LEVELS CIL_CONSTRAIN_KEYS #define CIL_CONSTRAIN_OPER "== != eq dom domby incomp not and or" struct cil_constrain { struct cil_list *classperms; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_validatetrans { char *class_str; struct cil_class *class; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_param { char *str; enum cil_flavor flavor; }; struct cil_macro { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; struct cil_list *params; }; struct cil_args { char *arg_str; struct cil_symtab_datum *arg; char *param_str; enum cil_flavor flavor; }; struct cil_call { char *macro_str; struct cil_macro *macro; struct cil_tree *args_tree; struct cil_list *args; int copied; }; #define CIL_TRUE 1 #define CIL_FALSE 0 struct cil_condblock { enum cil_flavor flavor; symtab_t symtab[CIL_SYM_NUM]; }; struct cil_booleanif { struct cil_list *str_expr; struct cil_list *datum_expr; int preserved_tunable; }; struct cil_tunableif { struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_policycap { struct cil_symtab_datum datum; }; struct cil_bounds { char *parent_str; char *child_str; }; /* Ensure that CIL uses the same values as sepol policydb.h */ enum cil_default_object { CIL_DEFAULT_SOURCE = DEFAULT_SOURCE, CIL_DEFAULT_TARGET = DEFAULT_TARGET, }; /* Default labeling behavior for users, roles, and types */ struct cil_default { enum cil_flavor flavor; struct cil_list *class_strs; struct cil_list *class_datums; enum cil_default_object object; }; /* Ensure that CIL uses the same values as sepol policydb.h */ enum cil_default_object_range { CIL_DEFAULT_SOURCE_LOW = DEFAULT_SOURCE_LOW, CIL_DEFAULT_SOURCE_HIGH = DEFAULT_SOURCE_HIGH, CIL_DEFAULT_SOURCE_LOW_HIGH = DEFAULT_SOURCE_LOW_HIGH, CIL_DEFAULT_TARGET_LOW = DEFAULT_TARGET_LOW, CIL_DEFAULT_TARGET_HIGH = DEFAULT_TARGET_HIGH, CIL_DEFAULT_TARGET_LOW_HIGH = DEFAULT_TARGET_LOW_HIGH, }; /* Default labeling behavior for range */ struct cil_defaultrange { struct cil_list *class_strs; struct cil_list *class_datums; enum cil_default_object_range object_range; }; struct cil_handleunknown { int handle_unknown; }; struct cil_mls { int value; }; struct cil_src_info { int is_cil; char *path; }; void cil_db_init(struct cil_db **db); void cil_db_destroy(struct cil_db **db); void cil_root_init(struct cil_root **root); void cil_root_destroy(struct cil_root *root); void cil_destroy_data(void **data, enum cil_flavor flavor); int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *index); const char * cil_node_to_string(struct cil_tree_node *node); int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size); int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size); int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size); void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]); void cil_symtab_array_destroy(symtab_t symtab[]); void cil_destroy_ast_symtabs(struct cil_tree_node *root); int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index); void cil_sort_init(struct cil_sort **sort); void cil_sort_destroy(struct cil_sort **sort); void cil_netifcon_init(struct cil_netifcon **netifcon); void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon); void cil_context_init(struct cil_context **context); void cil_level_init(struct cil_level **level); void cil_levelrange_init(struct cil_levelrange **lvlrange); void cil_sens_init(struct cil_sens **sens); void cil_block_init(struct cil_block **block); void cil_blockinherit_init(struct cil_blockinherit **inherit); void cil_blockabstract_init(struct cil_blockabstract **abstract); void cil_in_init(struct cil_in **in); void cil_class_init(struct cil_class **class); void cil_classorder_init(struct cil_classorder **classorder); void cil_classcommon_init(struct cil_classcommon **classcommon); void cil_sid_init(struct cil_sid **sid); void cil_sidcontext_init(struct cil_sidcontext **sidcontext); void cil_sidorder_init(struct cil_sidorder **sidorder); void cil_userrole_init(struct cil_userrole **userrole); void cil_userprefix_init(struct cil_userprefix **userprefix); void cil_selinuxuser_init(struct cil_selinuxuser **selinuxuser); void cil_roleattribute_init(struct cil_roleattribute **attribute); void cil_roleattributeset_init(struct cil_roleattributeset **attrset); void cil_roletype_init(struct cil_roletype **roletype); void cil_typeattribute_init(struct cil_typeattribute **attribute); void cil_typeattributeset_init(struct cil_typeattributeset **attrset); void cil_expandtypeattribute_init(struct cil_expandtypeattribute **expandattr); void cil_alias_init(struct cil_alias **alias); void cil_aliasactual_init(struct cil_aliasactual **aliasactual); void cil_typepermissive_init(struct cil_typepermissive **typeperm); void cil_name_init(struct cil_name **name); void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans); void cil_rangetransition_init(struct cil_rangetransition **rangetrans); void cil_bool_init(struct cil_bool **cilbool); void cil_boolif_init(struct cil_booleanif **bif); void cil_condblock_init(struct cil_condblock **cb); void cil_tunable_init(struct cil_tunable **ciltun); void cil_tunif_init(struct cil_tunableif **tif); void cil_avrule_init(struct cil_avrule **avrule); void cil_permissionx_init(struct cil_permissionx **permx); void cil_type_rule_init(struct cil_type_rule **type_rule); void cil_roletransition_init(struct cil_roletransition **roletrans); void cil_roleallow_init(struct cil_roleallow **role_allow); void cil_catset_init(struct cil_catset **catset); void cil_cats_init(struct cil_cats **cats); void cil_senscat_init(struct cil_senscat **senscat); void cil_filecon_init(struct cil_filecon **filecon); void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon); void cil_portcon_init(struct cil_portcon **portcon); void cil_nodecon_init(struct cil_nodecon **nodecon); void cil_genfscon_init(struct cil_genfscon **genfscon); void cil_pirqcon_init(struct cil_pirqcon **pirqcon); void cil_iomemcon_init(struct cil_iomemcon **iomemcon); void cil_ioportcon_init(struct cil_ioportcon **ioportcon); void cil_pcidevicecon_init(struct cil_pcidevicecon **pcidevicecon); void cil_devicetreecon_init(struct cil_devicetreecon **devicetreecon); void cil_fsuse_init(struct cil_fsuse **fsuse); void cil_constrain_init(struct cil_constrain **constrain); void cil_validatetrans_init(struct cil_validatetrans **validtrans); void cil_ipaddr_init(struct cil_ipaddr **ipaddr); void cil_perm_init(struct cil_perm **perm); void cil_classpermission_init(struct cil_classpermission **cp); void cil_classpermissionset_init(struct cil_classpermissionset **cps); void cil_classperms_set_init(struct cil_classperms_set **cp_set); void cil_classperms_init(struct cil_classperms **cp); void cil_classmapping_init(struct cil_classmapping **mapping); void cil_user_init(struct cil_user **user); void cil_userlevel_init(struct cil_userlevel **usrlvl); void cil_userrange_init(struct cil_userrange **userrange); void cil_role_init(struct cil_role **role); void cil_type_init(struct cil_type **type); void cil_cat_init(struct cil_cat **cat); void cil_catorder_init(struct cil_catorder **catorder); void cil_sensorder_init(struct cil_sensorder **sensorder); void cil_args_init(struct cil_args **args); void cil_call_init(struct cil_call **call); void cil_optional_init(struct cil_optional **optional); void cil_param_init(struct cil_param **param); void cil_macro_init(struct cil_macro **macro); void cil_policycap_init(struct cil_policycap **policycap); void cil_bounds_init(struct cil_bounds **bounds); void cil_default_init(struct cil_default **def); void cil_defaultrange_init(struct cil_defaultrange **def); void cil_handleunknown_init(struct cil_handleunknown **unk); void cil_mls_init(struct cil_mls **mls); void cil_src_info_init(struct cil_src_info **info); void cil_userattribute_init(struct cil_userattribute **attribute); void cil_userattributeset_init(struct cil_userattributeset **attrset); #endif libsepol/cil/src/cil_lexer.h0100644 0000000 0000000 00000004011 13756670065 015106 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_LEXER_H_ #define CIL_LEXER_H_ #include #define OPAREN 1 #define CPAREN 2 #define SYMBOL 3 #define QSTRING 4 #define COMMENT 5 #define HLL_LINEMARK 6 #define NEWLINE 7 #define END_OF_FILE 8 #define UNKNOWN 9 struct token { uint32_t type; char * value; uint32_t line; }; int cil_lexer_setup(char *buffer, uint32_t size); void cil_lexer_destroy(void); int cil_lexer_next(struct token *tok); #endif /* CIL_LEXER_H_ */ libsepol/cil/src/cil_lexer.l0100644 0000000 0000000 00000005440 13756670065 015121 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ %{ #include #include #include "cil_internal.h" #include "cil_lexer.h" #include "cil_log.h" #include "cil_mem.h" char *value = NULL; int line = 1; %} %option nounput %option noinput %option noyywrap %option prefix="cil_yy" digit [0-9] alpha [a-zA-Z] spec_char [\[\]\.\@\=\/\*\-\_\$\%\+\-\!\|\&\^\:\~\`\#\{\}\'\<\>\?\,] symbol ({digit}|{alpha}|{spec_char})+ white [ \t] newline [\n\r] qstring \"[^"\n]*\" hll_lm ^;;\* comment ; %% {newline} line++; return NEWLINE; {hll_lm} value=yytext; return HLL_LINEMARK; {comment} value=yytext; return COMMENT; "(" value=yytext; return OPAREN; ")" value=yytext; return CPAREN; {symbol} value=yytext; return SYMBOL; {white} ; {qstring} value=yytext; return QSTRING; <> return END_OF_FILE; . value=yytext; return UNKNOWN; %% int cil_lexer_setup(char *buffer, uint32_t size) { size = (yy_size_t)size; if (yy_scan_buffer(buffer, size) == NULL) { cil_log(CIL_INFO, "Lexer failed to setup buffer\n"); return SEPOL_ERR; } line = 1; return SEPOL_OK; } void cil_lexer_destroy(void) { yylex_destroy(); } int cil_lexer_next(struct token *tok) { tok->type = yylex(); tok->value = value; tok->line = line; return SEPOL_OK; } libsepol/cil/src/cil_list.c0100644 0000000 0000000 00000014547 13756670065 014754 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_list_error(const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(CIL_ERR, msg, ap); va_end(ap); exit(1); } void cil_list_init(struct cil_list **list, enum cil_flavor flavor) { struct cil_list *new_list = cil_malloc(sizeof(*new_list)); new_list->head = NULL; new_list->tail = NULL; new_list->flavor = flavor; *list = new_list; } void cil_list_destroy(struct cil_list **list, unsigned destroy_data) { if (*list == NULL) { return; } struct cil_list_item *item = (*list)->head; struct cil_list_item *next = NULL; while (item != NULL) { next = item->next; if (item->flavor == CIL_LIST) { cil_list_destroy((struct cil_list**)&(item->data), destroy_data); free(item); } else { cil_list_item_destroy(&item, destroy_data); } item = next; } free(*list); *list = NULL; } void cil_list_item_init(struct cil_list_item **item) { struct cil_list_item *new_item = cil_malloc(sizeof(*new_item)); new_item->next = NULL; new_item->flavor = CIL_NONE; new_item->data = NULL; *item = new_item; } void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data) { if (destroy_data) { cil_destroy_data(&(*item)->data, (*item)->flavor); } free(*item); *item = NULL; } void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to append data to a NULL list"); } cil_list_item_init(&item); item->flavor = flavor; item->data = data; if (list->tail == NULL) { list->head = item; list->tail = item; return; } list->tail->next = item; list->tail = item; } void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to prepend data to a NULL list"); } cil_list_item_init(&item); item->flavor = flavor; item->data = data; if (list->tail == NULL) { list->head = item; list->tail = item; return; } item->next = list->head; list->head = item; } struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to append data to a NULL list"); } if (curr == NULL) { /* Insert at the front of the list */ cil_list_prepend(list, flavor, data); return list->head; } if (curr == list->tail) { cil_list_append(list, flavor, data); return list->tail; } cil_list_item_init(&item); item->flavor = flavor; item->data = data; item->next = curr->next; curr->next = item; return item; } void cil_list_append_item(struct cil_list *list, struct cil_list_item *item) { struct cil_list_item *last = item; if (list == NULL) { cil_list_error("Attempt to append an item to a NULL list"); } if (item == NULL) { cil_list_error("Attempt to append a NULL item to a list"); } while (last->next != NULL) { last = last->next; } if (list->tail == NULL) { list->head = item; list->tail = last; return; } list->tail->next = item; list->tail = last; } void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item) { struct cil_list_item *last = item; if (list == NULL) { cil_list_error("Attempt to prepend an item to a NULL list"); } if (item == NULL) { cil_list_error("Attempt to prepend a NULL item to a list"); } while (last->next != NULL) { last = last->next; } if (list->tail == NULL) { list->head = item; list->tail = last; return; } last->next = list->head; list->head = item; } void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data) { struct cil_list_item *item; struct cil_list_item *previous = NULL; if (list == NULL) { cil_list_error("Attempt to remove data from a NULL list"); } cil_list_for_each(item, list) { if (item->data == data && item->flavor == flavor) { if (previous == NULL) { list->head = item->next; } else { previous->next = item->next; } if (item->next == NULL) { list->tail = previous; } cil_list_item_destroy(&item, destroy_data); break; } previous = item; } } int cil_list_contains(struct cil_list *list, void *data) { struct cil_list_item *curr = NULL; cil_list_for_each(curr, list) { if (curr->data == data) { return CIL_TRUE; } } return CIL_FALSE; } int cil_list_match_any(struct cil_list *l1, struct cil_list *l2) { struct cil_list_item *i1; struct cil_list_item *i2; cil_list_for_each(i1, l1) { cil_list_for_each(i2, l2) { if (i1->data == i2->data && i1->flavor == i2->flavor) { return CIL_TRUE; } } } return CIL_FALSE; } libsepol/cil/src/cil_list.h0100644 0000000 0000000 00000005566 13756670065 014762 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_LIST_H_ #define CIL_LIST_H_ #include "cil_flavor.h" struct cil_list { struct cil_list_item *head; struct cil_list_item *tail; enum cil_flavor flavor; }; struct cil_list_item { struct cil_list_item *next; enum cil_flavor flavor; void *data; }; #define cil_list_for_each(item, list) \ for (item = (list)->head; item != NULL; item = item->next) void cil_list_init(struct cil_list **list, enum cil_flavor flavor); void cil_list_destroy (struct cil_list **list, unsigned destroy_data); void cil_list_item_init(struct cil_list_item **item); void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data); void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data); void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data); void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data); struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data); void cil_list_append_item(struct cil_list *list, struct cil_list_item *item); void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item); int cil_list_contains(struct cil_list *list, void *data); int cil_list_match_any(struct cil_list *l1, struct cil_list *l2); #endif libsepol/cil/src/cil_log.c0100644 0000000 0000000 00000005036 13756670065 014553 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_log.h" static enum cil_log_level cil_log_level = CIL_ERR; void cil_default_log_handler(__attribute__((unused)) int lvl, char *msg) { fprintf(stderr, "%s", msg); } void (*cil_log_handler)(int lvl, char *msg) = &cil_default_log_handler; void cil_set_log_handler(void (*handler)(int lvl, char *msg)) { cil_log_handler = handler; } __attribute__ ((format (printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args) { if (cil_log_level >= lvl) { char buff[MAX_LOG_SIZE]; vsnprintf(buff, MAX_LOG_SIZE, msg, args); (*cil_log_handler)(cil_log_level, buff); } } __attribute__ ((format (printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...) { va_list args; va_start(args, msg); cil_vlog(lvl, msg, args); va_end(args); } void cil_set_log_level(enum cil_log_level lvl) { cil_log_level = lvl; } libsepol/cil/src/cil_log.h0100644 0000000 0000000 00000003660 13756670065 014561 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_LOG_H_ #define CIL_LOG_H_ #include #include #include #define MAX_LOG_SIZE 512 __attribute__ ((format(printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args); __attribute__ ((format(printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...); #endif // CIL_LOG_H_ libsepol/cil/src/cil_mem.c0100644 0000000 0000000 00000005637 13756670065 014557 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_log.h" __attribute__((noreturn)) void cil_default_mem_error_handler(void) { cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } void (*cil_mem_error_handler)(void) = &cil_default_mem_error_handler; void cil_set_mem_error_handler(void (*handler)(void)) { cil_mem_error_handler = handler; } void *cil_malloc(size_t size) { void *mem = malloc(size); if (mem == NULL){ if (size == 0) { return NULL; } (*cil_mem_error_handler)(); } return mem; } void *cil_calloc(size_t num_elements, size_t element_size) { void *mem = calloc(num_elements, element_size); if (mem == NULL){ (*cil_mem_error_handler)(); } return mem; } void *cil_realloc(void *ptr, size_t size) { void *mem = realloc(ptr, size); if (mem == NULL){ if (size == 0) { return NULL; } (*cil_mem_error_handler)(); } return mem; } char *cil_strdup(const char *str) { char *mem = NULL; if (str == NULL) { return NULL; } mem = strdup(str); if (mem == NULL) { (*cil_mem_error_handler)(); } return mem; } __attribute__ ((format (printf, 2, 3))) int cil_asprintf(char **strp, const char *fmt, ...) { int rc; va_list ap; va_start(ap, fmt); rc = vasprintf(strp, fmt, ap); va_end(ap); if (rc == -1) { (*cil_mem_error_handler)(); } return rc; } libsepol/cil/src/cil_mem.h0100644 0000000 0000000 00000003726 13756670065 014561 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_MEM_H_ #define CIL_MEM_H_ /* Wrapped malloc that catches errors and calls the error callback */ void *cil_malloc(size_t size); void *cil_calloc(size_t num_elements, size_t element_size); void *cil_realloc(void *ptr, size_t size); char *cil_strdup(const char *str); int cil_asprintf(char **strp, const char *fmt, ...); void (*cil_mem_error_handler)(void); #endif /* CIL_MEM_H_ */ libsepol/cil/src/cil_parser.c0100644 0000000 0000000 00000020332 13756670065 015262 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_lexer.h" #include "cil_strpool.h" #include "cil_stack.h" char *CIL_KEY_HLL_LMS; char *CIL_KEY_HLL_LMX; char *CIL_KEY_HLL_LME; struct hll_info { int hll_lineno; int hll_expand; }; static void push_hll_info(struct cil_stack *stack, int hll_lineno, int hll_expand) { struct hll_info *new = cil_malloc(sizeof(*new)); new->hll_lineno = hll_lineno; new->hll_expand = hll_expand; cil_stack_push(stack, CIL_NONE, new); } static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expand) { struct cil_stack_item *curr = cil_stack_pop(stack); struct cil_stack_item *prev = cil_stack_peek(stack); struct hll_info *old; free(curr->data); if (!prev) { *hll_lineno = -1; *hll_expand = -1; } else { old = prev->data; *hll_lineno = old->hll_lineno; *hll_expand = old->hll_expand; } } static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, int line, int hll_line, void *value) { cil_tree_node_init(node); (*node)->parent = current; (*node)->flavor = CIL_NODE; (*node)->line = line; (*node)->hll_line = hll_line; (*node)->data = value; } static void insert_node(struct cil_tree_node *node, struct cil_tree_node *current) { if (current->cl_head == NULL) { current->cl_head = node; } else { current->cl_tail->next = node; } current->cl_tail = node; } static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int *hll_expand, struct cil_stack *stack, char *path) { char *hll_type; struct cil_tree_node *node; struct token tok; char *hll_file; char *end = NULL; cil_lexer_next(&tok); hll_type = cil_strpool_add(tok.value); if (hll_type == CIL_KEY_HLL_LME) { if (cil_stack_is_empty(stack)) { cil_log(CIL_ERR, "Line mark end without start\n"); goto exit; } pop_hll_info(stack, hll_lineno, hll_expand); *current = (*current)->parent; } else { create_node(&node, *current, tok.line, *hll_lineno, NULL); insert_node(node, *current); *current = node; create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO); insert_node(node, *current); create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_HLL); insert_node(node, *current); if (hll_type == CIL_KEY_HLL_LMS) { *hll_expand = 0; } else if (hll_type == CIL_KEY_HLL_LMX) { *hll_expand = 1; } else { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } cil_lexer_next(&tok); if (tok.type != SYMBOL) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } *hll_lineno = strtol(tok.value, &end, 10); if (errno == ERANGE || *end != '\0') { cil_log(CIL_ERR, "Problem parsing line number for line mark\n"); goto exit; } push_hll_info(stack, *hll_lineno, *hll_expand); cil_lexer_next(&tok); if (tok.type != SYMBOL && tok.type != QSTRING) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } if (tok.type == QSTRING) { tok.value[strlen(tok.value) - 1] = '\0'; tok.value = tok.value+1; } hll_file = cil_strpool_add(tok.value); create_node(&node, *current, tok.line, *hll_lineno, hll_file); insert_node(node, *current); } cil_lexer_next(&tok); if (tok.type != NEWLINE) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Problem with high-level line mark at line %d of %s\n", tok.line, path); return SEPOL_ERR; } static void add_cil_path(struct cil_tree_node **current, char *path) { struct cil_tree_node *node; create_node(&node, *current, 0, 0, NULL); insert_node(node, *current); *current = node; create_node(&node, *current, 0, 0, CIL_KEY_SRC_INFO); insert_node(node, *current); create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL); insert_node(node, *current); create_node(&node, *current, 0, 0, path); insert_node(node, *current); } int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree) { int paren_count = 0; struct cil_tree *tree = NULL; struct cil_tree_node *node = NULL; struct cil_tree_node *current = NULL; char *path = cil_strpool_add(_path); struct cil_stack *stack; int hll_lineno = -1; int hll_expand = -1; struct token tok; int rc = SEPOL_OK; CIL_KEY_HLL_LMS = cil_strpool_add("lms"); CIL_KEY_HLL_LMX = cil_strpool_add("lmx"); CIL_KEY_HLL_LME = cil_strpool_add("lme"); cil_stack_init(&stack); cil_lexer_setup(buffer, size); tree = *parse_tree; current = tree->root; add_cil_path(¤t, path); do { cil_lexer_next(&tok); switch (tok.type) { case HLL_LINEMARK: rc = add_hll_linemark(¤t, &hll_lineno, &hll_expand, stack, path); if (rc != SEPOL_OK) { goto exit; } break; case OPAREN: paren_count++; create_node(&node, current, tok.line, hll_lineno, NULL); insert_node(node, current); current = node; break; case CPAREN: paren_count--; if (paren_count < 0) { cil_log(CIL_ERR, "Close parenthesis without matching open at line %d of %s\n", tok.line, path); goto exit; } current = current->parent; break; case QSTRING: tok.value[strlen(tok.value) - 1] = '\0'; tok.value = tok.value+1; /* FALLTHRU */ case SYMBOL: if (paren_count == 0) { cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path); goto exit; } create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value)); insert_node(node, current); break; case NEWLINE : if (!hll_expand) { hll_lineno++; } break; case COMMENT: while (tok.type != NEWLINE && tok.type != END_OF_FILE) { cil_lexer_next(&tok); } if (!hll_expand) { hll_lineno++; } if (tok.type != END_OF_FILE) { break; } /* FALLTHRU */ // Fall through if EOF case END_OF_FILE: if (paren_count > 0) { cil_log(CIL_ERR, "Open parenthesis without matching close at line %d of %s\n", tok.line, path); goto exit; } if (!cil_stack_is_empty(stack)) { cil_log(CIL_ERR, "High-level language line marker start without close at line %d of %s\n", tok.line, path); goto exit; } break; case UNKNOWN: cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path); goto exit; default: cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path); goto exit; } } while (tok.type != END_OF_FILE); cil_lexer_destroy(); cil_stack_destroy(&stack); *parse_tree = tree; return SEPOL_OK; exit: while (!cil_stack_is_empty(stack)) { pop_hll_info(stack, &hll_lineno, &hll_expand); } cil_stack_destroy(&stack); return SEPOL_ERR; } libsepol/cil/src/cil_parser.h0100644 0000000 0000000 00000003403 13756670065 015267 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_PARSER_H_ #define CIL_PARSER_H_ #include "cil_tree.h" int cil_parser(char *path, char *buffer, uint32_t size, struct cil_tree **parse_tree); #endif /* CIL_PARSER_H_ */ libsepol/cil/src/cil_policy.c0100644 0000000 0000000 00000143741 13756670065 015277 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_find.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" enum cil_statement_list { CIL_LIST_COMMON = 1, CIL_LIST_DEFAULT_USER, CIL_LIST_DEFAULT_ROLE, CIL_LIST_DEFAULT_TYPE, CIL_LIST_DEFAULT_RANGE, CIL_LIST_SENSALIAS, CIL_LIST_CATALIAS, CIL_LIST_MLSCONSTRAIN, CIL_LIST_MLSVALIDATETRANS, CIL_LIST_POLICYCAP, CIL_LIST_TYPEATTRIBUTE, CIL_LIST_ROLEATTRIBUTE, CIL_LIST_BOOL, CIL_LIST_TYPE, CIL_LIST_TYPEALIAS, CIL_LIST_ROLE, CIL_LIST_ROLEALLOW, CIL_LIST_ROLETRANSITION, CIL_LIST_USER, CIL_LIST_CONSTRAINT, CIL_LIST_VALIDATETRANS, CIL_LIST_NUM_LISTS }; static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_list **lists; int kind = 0; lists = (struct cil_list **)extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_COMMON: kind = CIL_LIST_COMMON; break; case CIL_DEFAULTUSER: kind = CIL_LIST_DEFAULT_USER; break; case CIL_DEFAULTROLE: kind = CIL_LIST_DEFAULT_ROLE; break; case CIL_DEFAULTTYPE: kind = CIL_LIST_DEFAULT_TYPE; break; case CIL_DEFAULTRANGE: kind = CIL_LIST_DEFAULT_RANGE; break; case CIL_SENSALIAS: kind = CIL_LIST_SENSALIAS; break; case CIL_CATALIAS: kind = CIL_LIST_CATALIAS; break; case CIL_MLSCONSTRAIN: kind = CIL_LIST_MLSCONSTRAIN; break; case CIL_MLSVALIDATETRANS: kind = CIL_LIST_MLSVALIDATETRANS; break; case CIL_POLICYCAP: kind = CIL_LIST_POLICYCAP; break; case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { kind = CIL_LIST_TYPEATTRIBUTE; } break; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = node->data; if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { kind = CIL_LIST_ROLEATTRIBUTE; } break; } case CIL_BOOL: kind = CIL_LIST_BOOL; break; case CIL_TYPE: kind = CIL_LIST_TYPE; break; case CIL_TYPEALIAS: kind = CIL_LIST_TYPEALIAS; break; case CIL_ROLE: { struct cil_role *role = node->data; if (strcmp(role->datum.fqn, "object_r") != 0) { kind = CIL_LIST_ROLE; } break; } case CIL_ROLEALLOW: kind = CIL_LIST_ROLEALLOW; break; case CIL_ROLETRANSITION: kind = CIL_LIST_ROLETRANSITION; break; case CIL_USER: kind = CIL_LIST_USER; break; case CIL_CONSTRAIN: kind = CIL_LIST_CONSTRAINT; break; case CIL_VALIDATETRANS: kind = CIL_LIST_VALIDATETRANS; break; default: break; } if (kind > 0) { cil_list_append(lists[kind], node->flavor, node->data); } return SEPOL_OK; } static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[]) { cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists); } static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind) { struct cil_list_item *i1; cil_list_for_each(i1, rules) { fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn); } } static void cil_cats_to_policy(FILE *out, struct cil_cats *cats) { const char *lead = ""; struct cil_cat *first = NULL, *last = NULL, *cat; struct cil_list_item *i1; cil_list_for_each(i1, cats->datum_expr) { cat = i1->data; if (first == NULL) { first = cat; } else if (last == NULL) { if (cat->value == first->value + 1) { last = cat; } else { fprintf(out, "%s%s", lead, DATUM(first)->fqn); lead = ","; first = cat; } } else if (cat->value == last->value + 1) { last = cat; } else { fprintf(out, "%s%s", lead, DATUM(first)->fqn); lead = ","; if (last->value >= first->value + 1) { fprintf(out, "."); } else { fprintf(out, ","); } fprintf(out, "%s", DATUM(last)->fqn); first = cat; last = NULL; } } if (first) { fprintf(out, "%s%s", lead, DATUM(first)->fqn); if (last != NULL) { if (last->value >= first->value + 1) { fprintf(out, "."); } else { fprintf(out, ","); } fprintf(out, "%s", DATUM(last)->fqn); } } } static void cil_level_to_policy(FILE *out, struct cil_level *level) { fprintf(out, "%s", DATUM(level->sens)->fqn); if (level->cats != NULL) { fprintf(out, ":"); cil_cats_to_policy(out, level->cats); } } static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2) { /* Mostly just want to detect s0 - s0 ranges */ if (l1 == l2) return CIL_TRUE; if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL)) return CIL_TRUE; return CIL_FALSE; } static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange) { cil_level_to_policy(out, lvlrange->low); if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) { fprintf(out, " - "); cil_level_to_policy(out, lvlrange->high); } } static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls) { fprintf(out, "%s:", DATUM(context->user)->fqn); fprintf(out, "%s:", DATUM(context->role)->fqn); fprintf(out, "%s", DATUM(context->type)->fqn); if (mls) { fprintf(out, ":"); cil_levelrange_to_policy(out, context->range); } } static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first) { struct cil_list_item *i1 = expr->head; if (i1->flavor == CIL_OP) { enum cil_flavor op = (enum cil_flavor)i1->data; fprintf(out, "("); switch (op) { case CIL_NOT: fprintf(out, "! "); cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); break; case CIL_OR: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " || "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_AND: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " && "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_XOR: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " ^ "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_EQ: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " == "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_NEQ: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " != "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; default: fprintf(out, "???"); break; } fprintf(out, ")"); } else if (i1->flavor == CIL_DATUM) { if (first == CIL_TRUE) { fprintf(out, "("); } fprintf(out, "%s", DATUM(i1->data)->fqn); if (first == CIL_TRUE) { fprintf(out, ")"); } } else if (i1->flavor == CIL_LIST) { cil_cond_expr_to_policy(out, i1->data, CIL_FALSE); } else { fprintf(out, "???"); } } static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr) { ebitmap_node_t *unode; unsigned int i; size_t len = 0; ebitmap_for_each_bit(attr->users, unode, i) { if (!ebitmap_get_bit(attr->users, i)) continue; len += strlen(DATUM(db->val_to_user[i])->fqn); len++; } return len; } static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand) { struct cil_list_item *i1; enum cil_flavor flavor = operand->flavor; size_t len = 0; if (flavor == CIL_CONS_OPERAND) { len = 2; } else if (flavor == CIL_DATUM) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { len = __cil_userattribute_len(db, operand->data); len++; /* "{" */ } else { len = strlen(DATUM(operand->data)->fqn); } } else if (flavor == CIL_LIST) { len = 1; /* "{" */ cil_list_for_each(i1, (struct cil_list *)operand->data) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { len = __cil_userattribute_len(db, operand->data); } else { len += strlen(DATUM(operand->data)->fqn); len++; /* " " or "}" */ } } } return len; } static size_t __cil_cons_leaf_op_len(struct cil_list_item *op) { enum cil_flavor flavor = (enum cil_flavor)op->data; size_t len; switch (flavor) { case CIL_EQ: len = 4; /* " == " */ break; case CIL_NEQ: len = 4; /* " != " */ break; case CIL_CONS_DOM: len = 5; /* " dom " */ break; case CIL_CONS_DOMBY: len = 7; /* " domby " */ break; case CIL_CONS_INCOMP: len = 8; /* " incomp " */ break; default: /* Should be impossible to be here */ len = 5; /* " ??? " */ } return len; } static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr) { struct cil_list_item *i1; enum cil_flavor op; size_t len; i1 = cons_expr->head; op = (enum cil_flavor)i1->data; switch (op) { case CIL_NOT: len = 6; /* "(not )" */ len += cil_cons_expr_len(db, i1->next->data); break; case CIL_AND: len = 7; /* "( and )" */ len += cil_cons_expr_len(db, i1->next->data); len += cil_cons_expr_len(db, i1->next->next->data); break; case CIL_OR: len = 6; /* "( or )" */ len += cil_cons_expr_len(db, i1->next->data); len += cil_cons_expr_len(db, i1->next->next->data); break; default: len = 2; /* "()" */ len += __cil_cons_leaf_operand_len(db, i1->next); len += __cil_cons_leaf_op_len(i1); len += __cil_cons_leaf_operand_len(db, i1->next->next); } return len; } static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new) { ebitmap_node_t *unode; unsigned int i; char *str; size_t len; ebitmap_for_each_bit(attr->users, unode, i) { if (!ebitmap_get_bit(attr->users, i)) continue; str = DATUM(db->val_to_user[i])->fqn; len = strlen(str); memcpy(new, str, len); new += len; *new++ = ' '; } return new; } static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new) { struct cil_list_item *i1; enum cil_flavor flavor = operand->flavor; const char *o_str; size_t o_len; if (flavor == CIL_CONS_OPERAND) { enum cil_flavor o_flavor = (enum cil_flavor)operand->data; switch (o_flavor) { case CIL_CONS_U1: o_str = "u1"; break; case CIL_CONS_U2: o_str = "u2"; break; case CIL_CONS_U3: o_str = "u3"; break; case CIL_CONS_R1: o_str = "r1"; break; case CIL_CONS_R2: o_str = "r2"; break; case CIL_CONS_R3: o_str = "r3"; break; case CIL_CONS_T1: o_str = "t1"; break; case CIL_CONS_T2: o_str = "t2"; break; case CIL_CONS_T3: o_str = "t3"; break; case CIL_CONS_L1: o_str = "l1"; break; case CIL_CONS_L2: o_str = "l2"; break; case CIL_CONS_H1: o_str = "h1"; break; case CIL_CONS_H2: o_str = "h2"; break; default: /* Impossible */ o_str = "??"; } strcpy(new, o_str); new += 2; } else if (flavor == CIL_DATUM) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { *new++ = '{'; new = __cil_userattribute_to_string(db, operand->data, new); new--; *new++ = '}'; } else { o_str = DATUM(operand->data)->fqn; o_len = strlen(o_str); memcpy(new, o_str, o_len); new += o_len; } } else if (flavor == CIL_LIST) { *new++ = '{'; cil_list_for_each(i1, (struct cil_list *)operand->data) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { new = __cil_userattribute_to_string(db, operand->data, new); } else { o_str = DATUM(operand->data)->fqn; o_len = strlen(o_str); memcpy(new, o_str, o_len); new += o_len; *new++ = ' '; } } new--; *new++ = '}'; } return new; } static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new) { enum cil_flavor flavor = (enum cil_flavor)op->data; const char *op_str; size_t len; switch (flavor) { case CIL_EQ: op_str = " == "; len = 4; break; case CIL_NEQ: op_str = " != "; len = 4; break; case CIL_CONS_DOM: op_str = " dom "; len = 5; break; case CIL_CONS_DOMBY: op_str = " domby "; len = 7; break; case CIL_CONS_INCOMP: op_str = " incomp "; len = 8; break; default: /* Should be impossible to be here */ op_str = " ??? "; len = 5; } strcpy(new, op_str); new += len; return new; } static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new) { struct cil_list_item *i1; enum cil_flavor op; i1 = cons_expr->head; op = (enum cil_flavor)i1->data; switch (op) { case CIL_NOT: *new++ = '('; strcpy(new, "not "); new += 4; new = __cil_cons_expr_to_string(db, i1->next->data, new); *new++ = ')'; break; case CIL_AND: *new++ = '('; new = __cil_cons_expr_to_string(db, i1->next->data, new); strcpy(new, " and "); new += 5; new = __cil_cons_expr_to_string(db, i1->next->next->data, new); *new++ = ')'; break; case CIL_OR: *new++ = '('; new = __cil_cons_expr_to_string(db, i1->next->data, new); strcpy(new, " or "); new += 4; new = __cil_cons_expr_to_string(db, i1->next->next->data, new); *new++ = ')'; break; default: *new++ = '('; new = __cil_cons_leaf_operand_to_string(db, i1->next, new); new = __cil_cons_leaf_op_to_string(i1, new); new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new); *new++ = ')'; } return new; } static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr) { char *new, *tail; size_t len = cil_cons_expr_len(db, cons_expr); new = cil_malloc(len+1); tail = __cil_cons_expr_to_string(db, cons_expr, new); *tail = '\0'; return new; } static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs) { struct cil_list_item *i1; size_t len = 0; char *new, *curr; len += strlen(DATUM(classperms->class)->fqn) + 1; cil_list_for_each(i1, classperms->perms) { len += strlen(DATUM(i1->data)->fqn) + 1; } len += 4; /* for "{ " and " }" */ new = cil_malloc(len); curr = new; curr[len-1] = '\0'; len = strlen(DATUM(classperms->class)->fqn); memcpy(curr, DATUM(classperms->class)->fqn, len); curr += len; *curr++ = ' '; *curr++ = '{'; *curr++ = ' '; cil_list_for_each(i1, classperms->perms) { len = strlen(DATUM(i1->data)->fqn); memcpy(curr, DATUM(i1->data)->fqn, len); curr += len; *curr++ = ' '; } *curr++ = '}'; cil_list_append(classperms_strs, CIL_STRING, new); } static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs) { struct cil_list_item *i1; cil_list_for_each(i1, classperms) { if (i1->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i1->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_classperms_to_string(cp, classperms_strs); } else { /* MAP */ struct cil_list_item *i2 = NULL; cil_list_for_each(i2, cp->perms) { struct cil_perm *cmp = i2->data; cil_classperms_to_strings(cmp->classperms, classperms_strs); } } } else { /* SET */ struct cil_classperms_set *cp_set = i1->data; struct cil_classpermission *cp = cp_set->set; cil_classperms_to_strings(cp->classperms, classperms_strs); } } } static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder) { struct cil_list_item *i1; cil_list_for_each(i1, classorder) { fprintf(out, "class %s\n", DATUM(i1->data)->fqn); } } static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder) { struct cil_list_item *i1; cil_list_for_each(i1, sidorder) { fprintf(out, "sid %s\n", DATUM(i1->data)->fqn); } } static void cil_commons_to_policy(FILE *out, struct cil_list *commons) { struct cil_list_item *i1; struct cil_class* common; struct cil_tree_node *node; struct cil_tree_node *perm; cil_list_for_each(i1, commons) { common = i1->data; node = NODE(&common->datum); perm = node->cl_head; fprintf(out, "common %s {", common->datum.fqn); while (perm != NULL) { fprintf(out, "%s ", DATUM(perm->data)->fqn); perm = perm->next; } fprintf(out, "}\n"); } } static void cil_classes_to_policy(FILE *out, struct cil_list *classorder) { struct cil_list_item *i1; struct cil_class *class; struct cil_tree_node *node; cil_list_for_each(i1, classorder) { class = i1->data; node = NODE(&class->datum); fprintf(out, "class %s", class->datum.fqn); if (class->common != NULL) { fprintf(out, " inherits %s", class->common->datum.fqn); } if (node->cl_head != NULL) { struct cil_tree_node *perm = node->cl_head; fprintf(out, " {"); while (perm != NULL) { fprintf(out, " %s", DATUM(perm->data)->fqn); perm = perm->next; } fprintf(out, " }"); } fprintf(out, "\n"); } } static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind) { struct cil_list_item *i1, *i2, *i3; struct cil_default *def; struct cil_list *class_list; cil_list_for_each(i1, defaults) { def = i1->data; fprintf(out, "%s {",kind); cil_list_for_each(i2, def->class_datums) { class_list = cil_expand_class(i2->data); cil_list_for_each(i3, class_list) { fprintf(out, " %s", DATUM(i3->data)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } fprintf(out, " }"); if (def->object == CIL_DEFAULT_SOURCE) { fprintf(out," %s",CIL_KEY_SOURCE); } else if (def->object == CIL_DEFAULT_TARGET) { fprintf(out," %s",CIL_KEY_TARGET); } fprintf(out,";\n"); } } static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults) { struct cil_list_item *i1, *i2, *i3; struct cil_defaultrange *def; struct cil_list *class_list; cil_list_for_each(i1, defaults) { def = i1->data; fprintf(out, "default_range {"); cil_list_for_each(i2, def->class_datums) { class_list = cil_expand_class(i2->data); cil_list_for_each(i3, class_list) { fprintf(out, " %s", DATUM(i3->data)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } fprintf(out, " }"); switch (def->object_range) { case CIL_DEFAULT_SOURCE_LOW: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW); break; case CIL_DEFAULT_SOURCE_HIGH: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH); break; case CIL_DEFAULT_SOURCE_LOW_HIGH: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH); break; case CIL_DEFAULT_TARGET_LOW: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW); break; case CIL_DEFAULT_TARGET_HIGH: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH); break; case CIL_DEFAULT_TARGET_LOW_HIGH: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH); break; default: break; } fprintf(out,";\n"); } } static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_sens *sens; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_sens *actual; int num_aliases; cil_list_for_each(i1, sensorder) { sens = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (sens == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_SENSALIAS, alias); num_aliases++; } } fprintf(out, "sensitivity %s", sens->datum.fqn); if (num_aliases > 0) { fprintf(out, " alias"); if (num_aliases > 1) { fprintf(out, " {"); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } cil_list_destroy(&aliases, CIL_FALSE); } fprintf(out, ";\n"); } } static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder) { struct cil_list_item *item; struct cil_sens *sens; fprintf(out, "dominance {"); cil_list_for_each(item, sensorder) { sens = item->data; fprintf(out, " %s", sens->datum.fqn); } fprintf(out, " }\n"); } static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_sens *cat; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_sens *actual; int num_aliases; cil_list_for_each(i1, catorder) { cat = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (cat == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_CATALIAS, alias); num_aliases++; } } fprintf(out, "category %s",cat->datum.fqn); if (num_aliases > 0) { fprintf(out, " alias"); if (num_aliases > 1) { fprintf(out, " { "); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } cil_list_destroy(&aliases, CIL_FALSE); } fprintf(out, ";\n"); } } static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder) { struct cil_list_item *i1, *i2; struct cil_sens *sens; cil_list_for_each(i1, sensorder) { sens = i1->data; if (sens->cats_list) { cil_list_for_each(i2, sens->cats_list) { fprintf(out, "level %s:",sens->datum.fqn); cil_cats_to_policy(out, i2->data); fprintf(out,";\n"); } } else { fprintf(out, "level %s;\n",sens->datum.fqn); } } } static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains) { struct cil_list_item *i1, *i2; struct cil_constrain *cons; struct cil_list *classperms_strs; char *cp_str; char *expr_str; cil_list_for_each(i1, mlsconstrains) { cons = i1->data; cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(cons->classperms, classperms_strs); expr_str = cil_cons_expr_to_string(db, cons->datum_expr); cil_list_for_each(i2, classperms_strs) { cp_str = i2->data; fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str); free(cp_str); } free(expr_str); cil_list_destroy(&classperms_strs, CIL_FALSE); } } static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind) { struct cil_list_item *i1, *i2; struct cil_validatetrans *trans; struct cil_list *class_list; struct cil_class *class; char *expr_str; cil_list_for_each(i1, validatetrans) { trans = i1->data; class_list = cil_expand_class(trans->class); expr_str = cil_cons_expr_to_string(db, trans->datum_expr); cil_list_for_each(i2, class_list) { class = i2->data; fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str); } free(expr_str); cil_list_destroy(&class_list, CIL_FALSE); } } static void cil_bools_to_policy(FILE *out, struct cil_list *bools) { struct cil_list_item *i1; struct cil_bool *bool; const char *value; cil_list_for_each(i1, bools) { bool = i1->data; value = bool->value ? "true" : "false"; fprintf(out, "bool %s %s;\n", bool->datum.fqn, value); } } static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_type *type; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_type *actual; int num_aliases; cil_list_for_each(i1, types) { type = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (type == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_TYPEALIAS, alias); num_aliases++; } } if (num_aliases > 0) { fprintf(out, "typealias %s alias", type->datum.fqn); if (num_aliases > 1) { fprintf(out, " {"); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } fprintf(out, ";\n"); cil_list_destroy(&aliases, CIL_FALSE); } } } static void cil_typebounds_to_policy(FILE *out, struct cil_list *types) { struct cil_list_item *i1; struct cil_type *child; struct cil_type *parent; cil_list_for_each(i1, types) { child = i1->data; if (child->bounds != NULL) { parent = child->bounds; fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn); } } } static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes) { struct cil_list_item *i1, *i2; struct cil_type *type; struct cil_typeattribute *attribute; int first = CIL_TRUE; cil_list_for_each(i1, types) { type = i1->data; cil_list_for_each(i2, attributes) { attribute = i2->data; if (!attribute->keep) continue; if (ebitmap_get_bit(attribute->types, type->value)) { if (first) { fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn); first = CIL_FALSE; } else { fprintf(out, ", %s", attribute->datum.fqn); } } } if (!first) { fprintf(out, ";\n"); first = CIL_TRUE; } } } static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx) { ebitmap_node_t *node; unsigned int i, first = 0, last = 0; int need_first = CIL_TRUE, need_last = CIL_TRUE; const char *kind; if (permx->kind == CIL_PERMX_KIND_IOCTL) { kind = "ioctl"; } else { kind = "???"; } fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind); ebitmap_for_each_bit(permx->perms, node, i) { if (!ebitmap_get_bit(permx->perms, i)) continue; if (need_first == CIL_TRUE) { first = i; need_first = CIL_FALSE; } else if (need_last == CIL_TRUE) { if (i == first+1) { last = i; need_last = CIL_FALSE; } else { fprintf(out, " 0x%x", first); first = i; } } else if (i == last+1) { last = i; } else { if (last > first+1) { fprintf(out, " 0x%x-0x%x", first, last); } else { fprintf(out, " 0x%x 0x%x", first, last); } first = i; need_last = CIL_TRUE; } } if (need_first == CIL_FALSE) { if (need_last == CIL_FALSE) { fprintf(out, " 0x%x-0x%x", first, last); } else { fprintf(out, " 0x%x", first); } } fprintf(out," }"); } static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt; src = rule->src; tgt = rule->tgt; switch (rule->rule_kind) { case CIL_AVRULE_ALLOWED: kind = "allowxperm"; break; case CIL_AVRULE_AUDITALLOW: kind = "auditallowxperm"; break; case CIL_AVRULE_DONTAUDIT: kind = "dontauditxperm"; break; case CIL_AVRULE_NEVERALLOW: kind = "neverallowxperm"; break; default: kind = "???"; break; } fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn); cil_xperms_to_policy(out, rule->perms.x.permx); fprintf(out, ";\n"); } static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt; struct cil_list *classperms_strs; struct cil_list_item *i1; src = rule->src; tgt = rule->tgt; switch (rule->rule_kind) { case CIL_AVRULE_ALLOWED: kind = "allow"; break; case CIL_AVRULE_AUDITALLOW: kind = "auditallow"; break; case CIL_AVRULE_DONTAUDIT: kind = "dontaudit"; break; case CIL_AVRULE_NEVERALLOW: kind = "neverallow"; break; default: kind = "???"; break; } cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(rule->perms.classperms, classperms_strs); cil_list_for_each(i1, classperms_strs) { char *cp_str = i1->data; fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str); free(cp_str); } cil_list_destroy(&classperms_strs, CIL_FALSE); } static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt, *res; struct cil_list *class_list; struct cil_list_item *i1; src = rule->src; tgt = rule->tgt; res = rule->result; switch (rule->rule_kind) { case CIL_TYPE_TRANSITION: kind = "type_transition"; break; case CIL_TYPE_MEMBER: kind = "type_member"; break; case CIL_TYPE_CHANGE: kind = "type_change"; break; default: kind = "???"; break; } class_list = cil_expand_class(rule->obj); cil_list_for_each(i1, class_list) { fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans) { struct cil_symtab_datum *src, *tgt, *res; struct cil_name *name; struct cil_list *class_list; struct cil_list_item *i1; src = trans->src; tgt = trans->tgt; name = trans->name; res = trans->result; class_list = cil_expand_class(trans->obj); cil_list_for_each(i1, class_list) { fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans) { struct cil_symtab_datum *src, *exec; struct cil_list *class_list; struct cil_list_item *i1; src = trans->src; exec = trans->exec; class_list = cil_expand_class(trans->obj); cil_list_for_each(i1, class_list) { fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn); cil_levelrange_to_policy(out, trans->range); fprintf(out, ";\n"); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule) { fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn); } struct block_te_rules_extra { FILE *out; enum cil_flavor flavor; uint32_t rule_kind; }; static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct block_te_rules_extra *args = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_AVRULE: case CIL_AVRULEX: if (args->flavor == node->flavor) { struct cil_avrule *rule = node->data; if (args->rule_kind == rule->rule_kind) { if (rule->is_extended) { cil_av_rulex_to_policy(args->out, rule); } else { cil_av_rule_to_policy(args->out, rule); } } } break; case CIL_TYPE_RULE: if (args->flavor == node->flavor) { struct cil_type_rule *rule = node->data; if (args->rule_kind == rule->rule_kind) { cil_type_rule_to_policy(args->out, rule); } } break; case CIL_NAMETYPETRANSITION: if (args->flavor == node->flavor) { cil_nametypetransition_to_policy(args->out, node->data); } break; case CIL_RANGETRANSITION: if (args->flavor == node->flavor) { cil_rangetransition_to_policy(args->out, node->data); } break; case CIL_TYPEPERMISSIVE: if (args->flavor == node->flavor) { cil_typepermissive_to_policy(args->out, node->data); } break; default: break; } return SEPOL_OK; } static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls) { struct block_te_rules_extra args; args.out = out; args.flavor = CIL_TYPEPERMISSIVE; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_AVRULE; args.rule_kind = CIL_AVRULE_ALLOWED; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_AUDITALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_DONTAUDIT; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_NEVERALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_AVRULEX; args.rule_kind = CIL_AVRULE_ALLOWED; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_AUDITALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_DONTAUDIT; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_NEVERALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_TYPE_RULE; args.rule_kind = CIL_TYPE_TRANSITION; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_TYPE_MEMBER; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_TYPE_CHANGE; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_TYPE; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_NAMETYPETRANSITION; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); if (mls == CIL_TRUE) { args.flavor = CIL_RANGETRANSITION; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); } } struct te_rules_extra { FILE *out; int mls; }; static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct te_rules_extra *args = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: { struct cil_booleanif *bool = node->data; struct cil_tree_node *n; struct cil_condblock *cb; fprintf(args->out, "if "); cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE); fprintf(args->out," {\n"); n = node->cl_head; cb = n != NULL ? n->data : NULL; if (cb && cb->flavor == CIL_CONDTRUE) { cil_block_te_rules_to_policy(args->out, n, args->mls); n = n->next; cb = n != NULL ? n->data : NULL; } if (cb && cb->flavor == CIL_CONDFALSE) { fprintf(args->out,"} else {\n"); cil_block_te_rules_to_policy(args->out, n, args->mls); } fprintf(args->out,"}\n"); *finished = CIL_TREE_SKIP_HEAD; break; } default: break; } return SEPOL_OK; } static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls) { struct te_rules_extra args; args.out = out; args.mls = mls; cil_block_te_rules_to_policy(out, head, mls); cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args); } static void cil_roles_to_policy(FILE *out, struct cil_list *rules) { struct cil_list_item *i1; struct cil_role *role; cil_list_for_each(i1, rules) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; fprintf(out, "role %s;\n", role->datum.fqn); } } static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types) { struct cil_list_item *i1, *i2; struct cil_role *role; struct cil_type *type; int first = CIL_TRUE; cil_list_for_each(i1, roles) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; if (role->types) { cil_list_for_each(i2, types) { type = i2->data; if (ebitmap_get_bit(role->types, type->value)) { if (first) { fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn); first = CIL_FALSE; } else { fprintf(out, " %s", type->datum.fqn); } } } if (!first) { fprintf(out, " }"); first = CIL_TRUE; } fprintf(out, ";\n"); } } } static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes) { struct cil_list_item *i1, *i2; struct cil_role *role; struct cil_roleattribute *attribute; int first = CIL_TRUE; cil_list_for_each(i1, roles) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; cil_list_for_each(i2, attributes) { attribute = i2->data; if (ebitmap_get_bit(attribute->roles, role->value)) { if (first) { fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn); first = CIL_FALSE; } else { fprintf(out, ", %s", attribute->datum.fqn); } } } if (!first) { fprintf(out, ";\n"); first = CIL_TRUE; } } } static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows) { struct cil_list_item *i1; struct cil_roleallow *allow; cil_list_for_each(i1, roleallows) { allow = i1->data; fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn); } } static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions) { struct cil_list_item *i1, *i2; struct cil_list *class_list; struct cil_roletransition *trans; cil_list_for_each(i1, roletransitions) { trans = i1->data; class_list = cil_expand_class(trans->obj); cil_list_for_each(i2, class_list) { fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } } static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles) { struct cil_list_item *i1, *i2; struct cil_user *user; struct cil_list *roles = NULL; struct cil_role *role; int num_roles; cil_list_for_each(i1, users) { user = i1->data; num_roles = 0; fprintf(out, "user %s",user->datum.fqn); cil_list_for_each(i2, all_roles) { role = i2->data; if (ebitmap_get_bit(user->roles, role->value)) { if (num_roles == 0) { cil_list_init(&roles, CIL_LIST); } cil_list_append(roles, CIL_ROLE, role); num_roles++; } } if (num_roles > 0) { fprintf(out, " roles"); if (num_roles > 1) { fprintf(out, " {"); } cil_list_for_each(i2, roles) { role = i2->data; fprintf(out, " %s", role->datum.fqn); } if (num_roles > 1) { fprintf(out, " }"); } cil_list_destroy(&roles, CIL_FALSE); } if (mls == CIL_TRUE && user->dftlevel != NULL) { fprintf(out, " level "); cil_level_to_policy(out, user->dftlevel); } if (mls == CIL_TRUE && user->range != NULL) { fprintf(out, " range "); cil_levelrange_to_policy(out, user->range); } fprintf(out,";\n"); } } static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains) { struct cil_list_item *i1, *i2; struct cil_constrain *cons; struct cil_list *classperms_strs; char *cp_str; char *expr_str; cil_list_for_each(i1, constrains) { cons = i1->data; cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(cons->classperms, classperms_strs); expr_str = cil_cons_expr_to_string(db, cons->datum_expr); cil_list_for_each(i2, classperms_strs) { cp_str = i2->data; fprintf(out, "constrain %s %s;\n",cp_str, expr_str); free(cp_str); } free(expr_str); cil_list_destroy(&classperms_strs, CIL_FALSE); } } static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls) { struct cil_list_item *i1; struct cil_sid *sid; cil_list_for_each(i1, sids) { sid = i1->data; fprintf(out, "sid %s ", sid->datum.fqn); cil_context_to_policy(out, sid->context, mls); fprintf(out,"\n"); } } static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls) { unsigned i; struct cil_fsuse *fsuse; for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_XATTR) { fprintf(out, "fs_use_xattr %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_TASK) { fprintf(out, "fs_use_task %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_TRANS) { fprintf(out, "fs_use_trans %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } } static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls) { unsigned i; struct cil_genfscon *genfscon; for (i=0; icount; i++) { genfscon = genfscons->array[i]; fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str); cil_context_to_policy(out, genfscon->context, mls); fprintf(out, "\n"); } } static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls) { uint32_t i = 0; for (i = 0; i < ibpkeycons->count; i++) { struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i]; fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str); fprintf(out, "%d ", ibpkeycon->pkey_low); fprintf(out, "%d ", ibpkeycon->pkey_high); cil_context_to_policy(out, ibpkeycon->context, mls); fprintf(out, "\n"); } } static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls) { uint32_t i; for (i = 0; i < ibendportcons->count; i++) { struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i]; fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str); fprintf(out, "%u ", ibendportcon->port); cil_context_to_policy(out, ibendportcon->context, mls); fprintf(out, "\n"); } } static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls) { unsigned i; struct cil_portcon *portcon; for (i=0; icount; i++) { portcon = portcons->array[i]; fprintf(out, "portcon "); if (portcon->proto == CIL_PROTOCOL_UDP) { fprintf(out, "udp "); } else if (portcon->proto == CIL_PROTOCOL_TCP) { fprintf(out, "tcp "); } else if (portcon->proto == CIL_PROTOCOL_DCCP) { fprintf(out, "dccp "); } else if (portcon->proto == CIL_PROTOCOL_SCTP) { fprintf(out, "sctp "); } if (portcon->port_low == portcon->port_high) { fprintf(out, "%d ", portcon->port_low); } else { fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high); } cil_context_to_policy(out, portcon->context, mls); fprintf(out, "\n"); } } static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls) { unsigned i; struct cil_netifcon *netifcon; for (i=0; icount; i++) { netifcon = netifcons->array[i]; fprintf(out, "netifcon %s ", netifcon->interface_str); cil_context_to_policy(out, netifcon->if_context, mls); fprintf(out, " "); cil_context_to_policy(out, netifcon->packet_context, mls); fprintf(out, "\n"); } } static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls) { unsigned i; struct cil_nodecon *nodecon; char *addr, *mask; for (i=0; icount; i++) { nodecon = nodecons->array[i]; fprintf(out, "nodecon "); if (nodecon->addr->family == AF_INET) { errno = 0; addr = cil_malloc(INET_ADDRSTRLEN); inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",addr); } else { fprintf(out, "[INVALID] "); } free(addr); errno = 0; mask = cil_malloc(INET_ADDRSTRLEN); inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",mask); } else { fprintf(out, "[INVALID] "); } free(mask); } else { errno = 0; addr = cil_malloc(INET6_ADDRSTRLEN); inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",addr); } else { fprintf(out, "[INVALID] "); } free(addr); errno = 0; mask = cil_malloc(INET6_ADDRSTRLEN); inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",mask); } else { fprintf(out, "[INVALID] "); } free(mask); } cil_context_to_policy(out, nodecon->context, mls); fprintf(out, "\n"); } } static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls) { unsigned i; struct cil_pirqcon *pirqcon; for (i = 0; icount; i++) { pirqcon = pirqcons->array[i]; fprintf(out, "pirqcon %d ", pirqcon->pirq); cil_context_to_policy(out, pirqcon->context, mls); fprintf(out, ";\n"); } } static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls) { unsigned i; struct cil_iomemcon *iomemcon; for (i = 0; icount; i++) { iomemcon = iomemcons->array[i]; if (iomemcon->iomem_low == iomemcon->iomem_high) { fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low); } else { fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high); } cil_context_to_policy(out, iomemcon->context, mls); fprintf(out, ";\n"); } } static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls) { unsigned i; struct cil_ioportcon *ioportcon; for (i = 0; i < ioportcons->count; i++) { ioportcon = ioportcons->array[i]; fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high); cil_context_to_policy(out, ioportcon->context, mls); fprintf(out, ";\n"); } } static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls) { unsigned i; struct cil_pcidevicecon *pcidevicecon; for (i = 0; i < pcidevicecons->count; i++) { pcidevicecon = pcidevicecons->array[i]; fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev); cil_context_to_policy(out, pcidevicecon->context, mls); fprintf(out, ";\n"); } } static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls) { unsigned i; struct cil_devicetreecon *devicetreecon; for (i = 0; i < devicetreecons->count; i++) { devicetreecon = devicetreecons->array[i]; fprintf(out, "devicetreecon %s ", devicetreecon->path); cil_context_to_policy(out, devicetreecon->context, mls); fprintf(out, ";\n"); } } void cil_gen_policy(FILE *out, struct cil_db *db) { unsigned i; struct cil_tree_node *head = db->ast->root; struct cil_list *lists[CIL_LIST_NUM_LISTS]; for (i=0; iclassorder); cil_sid_decls_to_policy(out, db->sidorder); cil_commons_to_policy(out, lists[CIL_LIST_COMMON]); cil_classes_to_policy(out, db->classorder); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user"); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role"); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type"); if (db->mls == CIL_TRUE) { cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]); cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]); cil_dominance_to_policy(out, db->sensitivityorder); cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]); cil_levels_to_policy(out, db->sensitivityorder); cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]); cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS); } cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP); cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute"); cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role"); cil_bools_to_policy(out, lists[CIL_LIST_BOOL]); cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type"); cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]); cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]); cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]); cil_te_rules_to_policy(out, head, db->mls); cil_roles_to_policy(out, lists[CIL_LIST_ROLE]); cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]); cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]); cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]); cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]); cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]); cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]); cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS); cil_sid_contexts_to_policy(out, db->sidorder, db->mls); cil_fsuses_to_policy(out, db->fsuse, db->mls); cil_genfscons_to_policy(out, db->genfscon, db->mls); cil_portcons_to_policy(out, db->portcon, db->mls); cil_netifcons_to_policy(out, db->netifcon, db->mls); cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls); cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls); cil_nodecons_to_policy(out, db->nodecon, db->mls); cil_pirqcons_to_policy(out, db->pirqcon, db->mls); cil_iomemcons_to_policy(out, db->iomemcon, db->mls); cil_ioportcons_to_policy(out, db->ioportcon, db->mls); cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls); cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls); for (i=0; i #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_post.h" #include "cil_policy.h" #include "cil_verify.h" #include "cil_symtab.h" #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db); static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db); static int cats_compare(struct cil_cats *a, struct cil_cats *b) { struct cil_list_item *i, *j; int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; /* Expects cat expression to have been evaluated */ cil_list_for_each(i, a->datum_expr) { cil_list_for_each(j, b->datum_expr) { rc = strcmp(DATUM(i->data)->fqn, DATUM(j->data)->fqn); if (!rc) return rc; } } return 0; } static int level_compare(struct cil_level *a, struct cil_level *b) { int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; if (a->sens != b->sens) { rc = strcmp(DATUM(a->sens)->fqn, DATUM(b->sens)->fqn); if (rc != 0) return rc; } if (a->cats != b->cats) { return cats_compare(a->cats, b->cats); } return 0; } static int range_compare(struct cil_levelrange *a, struct cil_levelrange *b) { int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; if (a->low != b->low) { rc = level_compare(a->low, b->low); if (rc != 0) return rc; } if (a->high != b->high) { return level_compare(a->high, b->high); } return 0; } static int context_compare(struct cil_context *a, struct cil_context *b) { int rc; if (a->user != b->user) { rc = strcmp(DATUM(a->user)->fqn, DATUM(b->user)->fqn); if (rc != 0) return rc; } if (a->role != b->role) { rc = strcmp(DATUM(a->role)->fqn, DATUM(b->role)->fqn); if (rc != 0) return rc; } if (a->type != b->type) { rc = strcmp(DATUM(a->type)->fqn, DATUM(b->type)->fqn); if (rc != 0) return rc; } if (a->range != b->range) { return range_compare(a->range, b->range); } return 0; } static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor) { struct cil_list_item *curr; cil_list_for_each(curr, list) { switch (curr->flavor) { case CIL_LIST: return CIL_FALSE; break; case CIL_OP: return CIL_FALSE; break; default: if (flavor == CIL_CAT) { struct cil_symtab_datum *d = curr->data; struct cil_tree_node *n = d->nodes->head->data; if (n->flavor == CIL_CATSET) { return CIL_FALSE; } } break; } } return CIL_TRUE; } void cil_post_fc_fill_data(struct fc_data *fc, char *path) { int c = 0; fc->meta = 0; fc->stem_len = 0; fc->str_len = 0; while (path[c] != '\0') { switch (path[c]) { case '.': case '^': case '$': case '?': case '*': case '+': case '|': case '[': case '(': case '{': fc->meta = 1; break; case '\\': c++; /* FALLTHRU */ default: if (!fc->meta) { fc->stem_len++; } break; } fc->str_len++; c++; } } int cil_post_filecon_compare(const void *a, const void *b) { int rc = 0; struct cil_filecon *a_filecon = *(struct cil_filecon**)a; struct cil_filecon *b_filecon = *(struct cil_filecon**)b; struct fc_data *a_data = cil_malloc(sizeof(*a_data)); struct fc_data *b_data = cil_malloc(sizeof(*b_data)); char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1); a_path[0] = '\0'; char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1); b_path[0] = '\0'; strcat(a_path, a_filecon->path_str); strcat(b_path, b_filecon->path_str); cil_post_fc_fill_data(a_data, a_path); cil_post_fc_fill_data(b_data, b_path); if (a_data->meta && !b_data->meta) { rc = -1; } else if (b_data->meta && !a_data->meta) { rc = 1; } else if (a_data->stem_len < b_data->stem_len) { rc = -1; } else if (b_data->stem_len < a_data->stem_len) { rc = 1; } else if (a_data->str_len < b_data->str_len) { rc = -1; } else if (b_data->str_len < a_data->str_len) { rc = 1; } else if (a_filecon->type < b_filecon->type) { rc = -1; } else if (b_filecon->type < a_filecon->type) { rc = 1; } else { rc = strcmp(a_filecon->path_str, b_filecon->path_str); } free(a_path); free(b_path); free(a_data); free(b_data); return rc; } int cil_post_ibpkeycon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_ibpkeycon *aibpkeycon = *(struct cil_ibpkeycon **)a; struct cil_ibpkeycon *bibpkeycon = *(struct cil_ibpkeycon **)b; rc = strcmp(aibpkeycon->subnet_prefix_str, bibpkeycon->subnet_prefix_str); if (rc) return rc; rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low) - (bibpkeycon->pkey_high - bibpkeycon->pkey_low); if (rc == 0) { if (aibpkeycon->pkey_low < bibpkeycon->pkey_low) rc = -1; else if (bibpkeycon->pkey_low < aibpkeycon->pkey_low) rc = 1; } return rc; } int cil_post_portcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_portcon *aportcon = *(struct cil_portcon**)a; struct cil_portcon *bportcon = *(struct cil_portcon**)b; rc = (aportcon->port_high - aportcon->port_low) - (bportcon->port_high - bportcon->port_low); if (rc == 0) { if (aportcon->port_low < bportcon->port_low) { rc = -1; } else if (bportcon->port_low < aportcon->port_low) { rc = 1; } else if (aportcon->proto < bportcon->proto) { rc = -1; } else if (aportcon->proto > bportcon->proto) { rc = 1; } } return rc; } int cil_post_genfscon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_genfscon *agenfscon = *(struct cil_genfscon**)a; struct cil_genfscon *bgenfscon = *(struct cil_genfscon**)b; rc = strcmp(agenfscon->fs_str, bgenfscon->fs_str); if (rc == 0) { rc = strcmp(agenfscon->path_str, bgenfscon->path_str); } return rc; } int cil_post_netifcon_compare(const void *a, const void *b) { struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a; struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b; return strcmp(anetifcon->interface_str, bnetifcon->interface_str); } int cil_post_ibendportcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_ibendportcon *aibendportcon = *(struct cil_ibendportcon **)a; struct cil_ibendportcon *bibendportcon = *(struct cil_ibendportcon **)b; rc = strcmp(aibendportcon->dev_name_str, bibendportcon->dev_name_str); if (rc) return rc; if (aibendportcon->port < bibendportcon->port) return -1; else if (bibendportcon->port < aibendportcon->port) return 1; return rc; } int cil_post_nodecon_compare(const void *a, const void *b) { struct cil_nodecon *anodecon; struct cil_nodecon *bnodecon; anodecon = *(struct cil_nodecon**)a; bnodecon = *(struct cil_nodecon**)b; /* sort ipv4 before ipv6 */ if (anodecon->addr->family != bnodecon->addr->family) { if (anodecon->addr->family == AF_INET) { return -1; } else { return 1; } } /* most specific netmask goes first, then order by ip addr */ if (anodecon->addr->family == AF_INET) { int rc = memcmp(&anodecon->mask->ip.v4, &bnodecon->mask->ip.v4, sizeof(anodecon->mask->ip.v4)); if (rc != 0) { return -1 * rc; } return memcmp(&anodecon->addr->ip.v4, &bnodecon->addr->ip.v4, sizeof(anodecon->addr->ip.v4)); } else { int rc = memcmp(&anodecon->mask->ip.v6, &bnodecon->mask->ip.v6, sizeof(anodecon->mask->ip.v6)); if (rc != 0) { return -1 * rc; } return memcmp(&anodecon->addr->ip.v6, &bnodecon->addr->ip.v6, sizeof(anodecon->addr->ip.v6)); } } int cil_post_pirqcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_pirqcon *apirqcon = *(struct cil_pirqcon**)a; struct cil_pirqcon *bpirqcon = *(struct cil_pirqcon**)b; if (apirqcon->pirq < bpirqcon->pirq) { rc = -1; } else if (bpirqcon->pirq < apirqcon->pirq) { rc = 1; } else { rc = 0; } return rc; } int cil_post_iomemcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a; struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b; rc = (aiomemcon->iomem_high - aiomemcon->iomem_low) - (biomemcon->iomem_high - biomemcon->iomem_low); if (rc == 0) { if (aiomemcon->iomem_low < biomemcon->iomem_low) { rc = -1; } else if (biomemcon->iomem_low < aiomemcon->iomem_low) { rc = 1; } } return rc; } int cil_post_ioportcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a; struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b; rc = (aioportcon->ioport_high - aioportcon->ioport_low) - (bioportcon->ioport_high - bioportcon->ioport_low); if (rc == 0) { if (aioportcon->ioport_low < bioportcon->ioport_low) { rc = -1; } else if (bioportcon->ioport_low < aioportcon->ioport_low) { rc = 1; } } return rc; } int cil_post_pcidevicecon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_pcidevicecon *apcidevicecon = *(struct cil_pcidevicecon**)a; struct cil_pcidevicecon *bpcidevicecon = *(struct cil_pcidevicecon**)b; if (apcidevicecon->dev < bpcidevicecon->dev) { rc = -1; } else if (bpcidevicecon->dev < apcidevicecon->dev) { rc = 1; } else { rc = 0; } return rc; } int cil_post_devicetreecon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_devicetreecon *adevicetreecon = *(struct cil_devicetreecon**)a; struct cil_devicetreecon *bdevicetreecon = *(struct cil_devicetreecon**)b; rc = strcmp(adevicetreecon->path, bdevicetreecon->path); return rc; } int cil_post_fsuse_compare(const void *a, const void *b) { int rc; struct cil_fsuse *afsuse; struct cil_fsuse *bfsuse; afsuse = *(struct cil_fsuse**)a; bfsuse = *(struct cil_fsuse**)b; if (afsuse->type < bfsuse->type) { rc = -1; } else if (bfsuse->type < afsuse->type) { rc = 1; } else { rc = strcmp(afsuse->fs_str, bfsuse->fs_str); } return rc; } int cil_post_filecon_context_compare(const void *a, const void *b) { struct cil_filecon *a_filecon = *(struct cil_filecon**)a; struct cil_filecon *b_filecon = *(struct cil_filecon**)b; return context_compare(a_filecon->context, b_filecon->context); } int cil_post_ibpkeycon_context_compare(const void *a, const void *b) { struct cil_ibpkeycon *a_ibpkeycon = *(struct cil_ibpkeycon **)a; struct cil_ibpkeycon *b_ibpkeycon = *(struct cil_ibpkeycon **)b; return context_compare(a_ibpkeycon->context, b_ibpkeycon->context); } int cil_post_portcon_context_compare(const void *a, const void *b) { struct cil_portcon *a_portcon = *(struct cil_portcon**)a; struct cil_portcon *b_portcon = *(struct cil_portcon**)b; return context_compare(a_portcon->context, b_portcon->context); } int cil_post_genfscon_context_compare(const void *a, const void *b) { struct cil_genfscon *a_genfscon = *(struct cil_genfscon**)a; struct cil_genfscon *b_genfscon = *(struct cil_genfscon**)b; return context_compare(a_genfscon->context, b_genfscon->context); } int cil_post_netifcon_context_compare(const void *a, const void *b) { int rc; struct cil_netifcon *a_netifcon = *(struct cil_netifcon**)a; struct cil_netifcon *b_netifcon = *(struct cil_netifcon**)b; rc = context_compare(a_netifcon->if_context, b_netifcon->if_context); if (rc != 0) { return rc; } return context_compare(a_netifcon->packet_context, b_netifcon->packet_context); } int cil_post_ibendportcon_context_compare(const void *a, const void *b) { struct cil_ibendportcon *a_ibendportcon = *(struct cil_ibendportcon **)a; struct cil_ibendportcon *b_ibendportcon = *(struct cil_ibendportcon **)b; return context_compare(a_ibendportcon->context, b_ibendportcon->context); } int cil_post_nodecon_context_compare(const void *a, const void *b) { struct cil_nodecon *a_nodecon = *(struct cil_nodecon **)a; struct cil_nodecon *b_nodecon = *(struct cil_nodecon **)b; return context_compare(a_nodecon->context, b_nodecon->context); } int cil_post_pirqcon_context_compare(const void *a, const void *b) { struct cil_pirqcon *a_pirqcon = *(struct cil_pirqcon**)a; struct cil_pirqcon *b_pirqcon = *(struct cil_pirqcon**)b; return context_compare(a_pirqcon->context, b_pirqcon->context); } int cil_post_iomemcon_context_compare(const void *a, const void *b) { struct cil_iomemcon *a_iomemcon = *(struct cil_iomemcon**)a; struct cil_iomemcon *b_iomemcon = *(struct cil_iomemcon**)b; return context_compare(a_iomemcon->context, b_iomemcon->context); } int cil_post_ioportcon_context_compare(const void *a, const void *b) { struct cil_ioportcon *a_ioportcon = *(struct cil_ioportcon**)a; struct cil_ioportcon *b_ioportcon = *(struct cil_ioportcon**)b; return context_compare(a_ioportcon->context, b_ioportcon->context); } int cil_post_pcidevicecon_context_compare(const void *a, const void *b) { struct cil_pcidevicecon *a_pcidevicecon = *(struct cil_pcidevicecon**)a; struct cil_pcidevicecon *b_pcidevicecon = *(struct cil_pcidevicecon**)b; return context_compare(a_pcidevicecon->context, b_pcidevicecon->context); } int cil_post_devicetreecon_context_compare(const void *a, const void *b) { struct cil_devicetreecon *a_devicetreecon = *(struct cil_devicetreecon**)a; struct cil_devicetreecon *b_devicetreecon = *(struct cil_devicetreecon**)b; return context_compare(a_devicetreecon->context, b_devicetreecon->context); } int cil_post_fsuse_context_compare(const void *a, const void *b) { struct cil_fsuse *a_fsuse = *(struct cil_fsuse**)a; struct cil_fsuse *b_fsuse = *(struct cil_fsuse**)b; return context_compare(a_fsuse->context, b_fsuse->context); } static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_db *db = extra_args; switch(node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_CLASS: { struct cil_class *class = node->data; if (class->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. db->num_classes++; } break; } case CIL_TYPE: { struct cil_type *type = node->data; if (type->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. type->value = db->num_types; db->num_types++; db->num_types_and_attrs++; } break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (attr->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. db->num_types_and_attrs++; } break; } case CIL_ROLE: { struct cil_role *role = node->data; if (role->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. role->value = db->num_roles; db->num_roles++; } break; } case CIL_USER: { struct cil_user *user = node->data; if (user->datum.nodes->head->data == node) { // multiple AST nodes can point to the same cil_user data (like if // copied from a macro). This check ensures we only count the // duplicates once user->value = db->num_users; db->num_users++; } break; } case CIL_NETIFCON: db->netifcon->count++; break; case CIL_GENFSCON: db->genfscon->count++; break; case CIL_FILECON: db->filecon->count++; break; case CIL_NODECON: db->nodecon->count++; break; case CIL_IBPKEYCON: db->ibpkeycon->count++; break; case CIL_IBENDPORTCON: db->ibendportcon->count++; break; case CIL_PORTCON: db->portcon->count++; break; case CIL_PIRQCON: db->pirqcon->count++; break; case CIL_IOMEMCON: db->iomemcon->count++; break; case CIL_IOPORTCON: db->ioportcon->count++; break; case CIL_PCIDEVICECON: db->pcidevicecon->count++; break; case CIL_DEVICETREECON: db->devicetreecon->count++; break; case CIL_FSUSE: db->fsuse->count++; break; default: break; } return SEPOL_OK; } static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_db *db = extra_args; switch(node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_TYPE: { struct cil_type *type = node->data; if (db->val_to_type == NULL) { db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types); } db->val_to_type[type->value] = type; break; } case CIL_ROLE: { struct cil_role *role = node->data; if (db->val_to_role == NULL) { db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles); } db->val_to_role[role->value] = role; break; } case CIL_USER: { struct cil_user *user= node->data; if (db->val_to_user == NULL) { db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users); } db->val_to_user[user->value] = user; break; } case CIL_USERPREFIX: { cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data); break; } case CIL_SELINUXUSER: { cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data); break; } case CIL_SELINUXUSERDEFAULT: { cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data); break; } case CIL_NETIFCON: { struct cil_sort *sort = db->netifcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IBENDPORTCON: { struct cil_sort *sort = db->ibendportcon; uint32_t count = sort->count; uint32_t i = sort->index; if (!sort->array) sort->array = cil_malloc(sizeof(*sort->array) * count); sort->array[i] = node->data; sort->index++; break; } case CIL_FSUSE: { struct cil_sort *sort = db->fsuse; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_GENFSCON: { struct cil_sort *sort = db->genfscon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_FILECON: { struct cil_sort *sort = db->filecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_NODECON: { struct cil_sort *sort = db->nodecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IBPKEYCON: { struct cil_sort *sort = db->ibpkeycon; uint32_t count = sort->count; uint32_t i = sort->index; if (!sort->array) sort->array = cil_malloc(sizeof(*sort->array) * count); sort->array[i] = node->data; sort->index++; break; } case CIL_PORTCON: { struct cil_sort *sort = db->portcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_PIRQCON: { struct cil_sort *sort = db->pirqcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IOMEMCON: { struct cil_sort *sort = db->iomemcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IOPORTCON: { struct cil_sort *sort = db->ioportcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_PCIDEVICECON: { struct cil_sort *sort = db->pcidevicecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_DEVICETREECON: { struct cil_sort *sort = db->devicetreecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } default: break; } return SEPOL_OK; } static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db) { int rc; attr->types = cil_malloc(sizeof(*attr->types)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n"); ebitmap_destroy(attr->types); free(attr->types); attr->types = NULL; } return rc; } static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; if (attr->types == NULL) { rc = __evaluate_type_expression(attr, db); if (rc != SEPOL_OK) goto exit; } ebitmap_union(bitmap, attr->types); } else if (node->flavor == CIL_TYPEALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_type *type = alias->actual; if (ebitmap_set_bit(bitmap, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(bitmap); goto exit; } } else { struct cil_type *type = (struct cil_type *)datum; if (ebitmap_set_bit(bitmap, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db) { int rc; attr->users = cil_malloc(sizeof(*attr->users)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n"); ebitmap_destroy(attr->users); free(attr->users); attr->users = NULL; } return rc; } static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; struct cil_userattribute *attr = NULL; struct cil_user *user = NULL; ebitmap_init(bitmap); if (node->flavor == CIL_USERATTRIBUTE) { attr = (struct cil_userattribute *)datum; if (attr->users == NULL) { rc = __evaluate_user_expression(attr, db); if (rc != SEPOL_OK) { goto exit; } } ebitmap_union(bitmap, attr->users); } else { user = (struct cil_user *)datum; if (ebitmap_set_bit(bitmap, user->value, 1)) { cil_log(CIL_ERR, "Failed to set user bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db) { int rc; attr->roles = cil_malloc(sizeof(*attr->roles)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n"); ebitmap_destroy(attr->roles); free(attr->roles); attr->roles = NULL; } return rc; } static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_ROLEATTRIBUTE) { struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; if (attr->roles == NULL) { rc = __evaluate_role_expression(attr, db); if (rc != SEPOL_OK) goto exit; } ebitmap_union(bitmap, attr->roles); } else { struct cil_role *role = (struct cil_role *)datum; if (ebitmap_set_bit(bitmap, role->value, 1)) { cil_log(CIL_ERR, "Failed to set role bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_permissionx_expression(struct cil_permissionx *permx, struct cil_db *db) { int rc; permx->perms = cil_malloc(sizeof(*permx->perms)); ebitmap_init(permx->perms); rc = __cil_expr_to_bitmap(permx->expr_str, permx->perms, 0x10000, db); // max is one more than 0xFFFF if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand permissionx expression\n"); ebitmap_destroy(permx->perms); free(permx->perms); permx->perms = NULL; } return rc; } static int __cil_permx_str_to_int(char *permx_str, uint16_t *val) { char *endptr = NULL; long lval = strtol(permx_str, &endptr, 0); if (*endptr != '\0') { cil_log(CIL_ERR, "permissionx value %s not valid number\n", permx_str); goto exit; } if (lval < 0x0000 || lval > 0xFFFF) { cil_log(CIL_ERR, "permissionx value %s must be between 0x0000 and 0xFFFF\n", permx_str); goto exit; } *val = (uint16_t)lval; return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_permx_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db) { int rc = SEPOL_ERR; uint16_t val; rc = __cil_permx_str_to_int((char*)datum, &val); if (rc != SEPOL_OK) { goto exit; } ebitmap_init(bitmap); if (ebitmap_set_bit(bitmap, (unsigned int)val, 1)) { cil_log(CIL_ERR, "Failed to set permissionx bit\n"); ebitmap_destroy(bitmap); goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db) { struct cil_perm *perm = (struct cil_perm *)datum; unsigned int value = perm->value; ebitmap_init(bitmap); if (ebitmap_set_bit(bitmap, value, 1)) { cil_log(CIL_INFO, "Failed to set perm bit\n"); ebitmap_destroy(bitmap); return SEPOL_ERR; } return SEPOL_OK; } static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db) { int rc = SEPOL_ERR; ebitmap_t bitmap; struct cil_list *new; struct cil_list_item *curr; if (cats->evaluated == CIL_TRUE) { return SEPOL_OK; } if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) { return SEPOL_OK; } ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n"); ebitmap_destroy(&bitmap); goto exit; } cil_list_init(&new, CIL_CAT); cil_list_for_each(curr, db->catorder) { struct cil_cat *cat = curr->data; if (ebitmap_get_bit(&bitmap, cat->value)) { cil_list_append(new, CIL_DATUM, cat); } } ebitmap_destroy(&bitmap); cil_list_destroy(&cats->datum_expr, CIL_FALSE); cats->datum_expr = new; cats->evaluated = CIL_TRUE; return SEPOL_OK; exit: return rc; } static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_CATSET) { struct cil_catset *catset = (struct cil_catset *)datum; struct cil_list_item *curr; if (catset->cats->evaluated == CIL_FALSE) { rc = __evaluate_cat_expression(catset->cats, db); if (rc != SEPOL_OK) goto exit; } for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) { struct cil_cat *cat = (struct cil_cat *)curr->data; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } } else if (node->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_cat *cat = alias->actual; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } else { struct cil_cat *cat = (struct cil_cat *)datum; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap) { int rc = SEPOL_ERR; struct cil_symtab_datum *d1 = i1->data; struct cil_symtab_datum *d2 = i2->data; struct cil_tree_node *n1 = d1->nodes->head->data; struct cil_tree_node *n2 = d2->nodes->head->data; struct cil_cat *c1 = (struct cil_cat *)d1; struct cil_cat *c2 = (struct cil_cat *)d2; int i; if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) { cil_log(CIL_ERR, "Category sets cannont be used in a category range\n"); goto exit; } if (n1->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)d1; c1 = alias->actual; } if (n2->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)d2; c2 = alias->actual; } if (c1->value > c2->value) { cil_log(CIL_ERR, "Invalid category range\n"); goto exit; } for (i = c1->value; i <= c2->value; i++) { if (ebitmap_set_bit(bitmap, i, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap) { int rc = SEPOL_ERR; char *p1 = i1->data; char *p2 = i2->data; uint16_t v1; uint16_t v2; uint32_t i; rc = __cil_permx_str_to_int(p1, &v1); if (rc != SEPOL_OK) { goto exit; } rc = __cil_permx_str_to_int(p2, &v2); if (rc != SEPOL_OK) { goto exit; } for (i = v1; i <= v2; i++) { if (ebitmap_set_bit(bitmap, i, 1)) { cil_log(CIL_ERR, "Failed to set permissionx bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db) { int rc = SEPOL_ERR; if (curr->flavor == CIL_DATUM) { switch (flavor) { case CIL_TYPE: rc = __cil_type_to_bitmap(curr->data, bitmap, db); break; case CIL_ROLE: rc = __cil_role_to_bitmap(curr->data, bitmap, db); break; case CIL_USER: rc = __cil_user_to_bitmap(curr->data, bitmap, db); break; case CIL_PERM: rc = __cil_perm_to_bitmap(curr->data, bitmap, db); break; case CIL_CAT: rc = __cil_cat_to_bitmap(curr->data, bitmap, db); break; default: rc = SEPOL_ERR; } } else if (curr->flavor == CIL_LIST) { struct cil_list *l = curr->data; ebitmap_init(bitmap); rc = __cil_expr_to_bitmap(l, bitmap, max, db); if (rc != SEPOL_OK) { ebitmap_destroy(bitmap); } } else if (flavor == CIL_PERMISSIONX) { // permissionx expressions aren't resolved into anything, so curr->flavor // is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those rc = __cil_permx_to_bitmap(curr->data, bitmap, db); } return rc; } static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; enum cil_flavor flavor; ebitmap_t tmp, b1, b2; if (expr == NULL || expr->head == NULL) { return SEPOL_OK; } curr = expr->head; flavor = expr->flavor; if (curr->flavor == CIL_OP) { enum cil_flavor op = (enum cil_flavor)curr->data; if (op == CIL_ALL) { ebitmap_init(&b1); /* all zeros */ rc = ebitmap_not(&tmp, &b1, max); ebitmap_destroy(&b1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand 'all' operator\n"); ebitmap_destroy(&tmp); goto exit; } } else if (op == CIL_RANGE) { if (flavor == CIL_CAT) { ebitmap_init(&tmp); rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); ebitmap_destroy(&tmp); goto exit; } } else if (flavor == CIL_PERMISSIONX) { ebitmap_init(&tmp); rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); ebitmap_destroy(&tmp); goto exit; } } else { cil_log(CIL_INFO, "Range operation only supported for categories permissionx\n"); rc = SEPOL_ERR; goto exit; } } else { rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get first operand bitmap\n"); goto exit; } if (op == CIL_NOT) { rc = ebitmap_not(&tmp, &b1, max); ebitmap_destroy(&b1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to NOT bitmap\n"); ebitmap_destroy(&tmp); goto exit; } } else { rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get second operand bitmap\n"); ebitmap_destroy(&b1); goto exit; } if (op == CIL_OR) { rc = ebitmap_or(&tmp, &b1, &b2); } else if (op == CIL_AND) { rc = ebitmap_and(&tmp, &b1, &b2); } else if (op == CIL_XOR) { rc = ebitmap_xor(&tmp, &b1, &b2); } else { rc = SEPOL_ERR; } ebitmap_destroy(&b1); ebitmap_destroy(&b2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n"); ebitmap_destroy(&tmp); goto exit; } } } } else { ebitmap_init(&tmp); for (;curr; curr = curr->next) { rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get operand in list\n"); ebitmap_destroy(&tmp); goto exit; } b1 = tmp; rc = ebitmap_or(&tmp, &b1, &b2); ebitmap_destroy(&b1); ebitmap_destroy(&b2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to OR operands in list\n"); ebitmap_destroy(&tmp); goto exit; } } } ebitmap_union(out, &tmp); ebitmap_destroy(&tmp); return SEPOL_OK; exit: return rc; } static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *expr; ebitmap_init(out); if (expr_list == NULL) { return SEPOL_OK; } cil_list_for_each(expr, expr_list) { ebitmap_t bitmap; struct cil_list *l = (struct cil_list *)expr->data; ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(l, &bitmap, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n"); ebitmap_destroy(&bitmap); goto exit; } ebitmap_union(out, &bitmap); ebitmap_destroy(&bitmap); } return SEPOL_OK; exit: return SEPOL_ERR; } static int cil_typeattribute_used(struct cil_typeattribute *attr, struct cil_db *db) { if (!attr->used) { return CIL_FALSE; } if (attr->used & CIL_ATTR_EXPAND_FALSE) { return CIL_TRUE; } if (attr->used & CIL_ATTR_EXPAND_TRUE) { return CIL_FALSE; } if (attr->used & CIL_ATTR_CONSTRAINT) { return CIL_TRUE; } if (db->attrs_expand_generated || attr->used == CIL_ATTR_NEVERALLOW) { if (strcmp(DATUM(attr)->name, GEN_REQUIRE_ATTR) == 0) { return CIL_FALSE; } else if (strstr(DATUM(attr)->name, TYPEATTR_INFIX) != NULL) { return CIL_FALSE; } if (attr->used == CIL_ATTR_NEVERALLOW) { return CIL_TRUE; } } if (attr->used == CIL_ATTR_AVRULE) { if (ebitmap_cardinality(attr->types) < db->attrs_expand_size) { return CIL_FALSE; } } return CIL_TRUE; } static void __mark_neverallow_attrs(struct cil_list *expr_list) { struct cil_list_item *curr; cil_list_for_each(curr, expr_list) { if (curr->flavor == CIL_DATUM) { if (NODE(curr->data)->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = curr->data; if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { __mark_neverallow_attrs(attr->expr_list); } else { attr->used |= CIL_ATTR_NEVERALLOW; } } } else if (curr->flavor == CIL_LIST) { __mark_neverallow_attrs(curr->data); } } } static int __cil_post_db_neverallow_attr_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) { switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if ((attr->used & CIL_ATTR_NEVERALLOW) && strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { __mark_neverallow_attrs(attr->expr_list); } break; } default: break; } return SEPOL_OK; } static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (attr->types == NULL) { rc = __evaluate_type_expression(attr, db); if (rc != SEPOL_OK) goto exit; } attr->keep = cil_typeattribute_used(attr, db); break; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = node->data; if (attr->roles == NULL) { rc = __evaluate_role_expression(attr, db); if (rc != SEPOL_OK) goto exit; } break; } case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (rule->perms.x.permx_str == NULL) { rc = __evaluate_permissionx_expression(rule->perms.x.permx, db); if (rc != SEPOL_OK) goto exit; } break; } case CIL_PERMISSIONX: { struct cil_permissionx *permx = node->data; rc = __evaluate_permissionx_expression(permx, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_USERATTRIBUTE: { struct cil_userattribute *attr = node->data; if (attr->users == NULL) { rc = __evaluate_user_expression(attr, db); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: return rc; } static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum) { struct cil_tree_node *node = datum->nodes->head->data; if (role->types == NULL) { role->types = cil_malloc(sizeof(*role->types)); ebitmap_init(role->types); } if (node->flavor == CIL_TYPE) { struct cil_type *type = (struct cil_type *)datum; if (ebitmap_set_bit(role->types, type->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n"); goto exit; } } else if (node->flavor == CIL_TYPEALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_type *type = alias->actual; if (ebitmap_set_bit(role->types, type->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n"); goto exit; } } else if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; ebitmap_union(role->types, attr->types); } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_post_db_roletype_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_ROLETYPE: { struct cil_roletype *roletype = node->data; struct cil_symtab_datum *role_datum = roletype->role; struct cil_symtab_datum *type_datum = roletype->type; struct cil_tree_node *role_node = role_datum->nodes->head->data; if (role_node->flavor == CIL_ROLEATTRIBUTE) { struct cil_roleattribute *attr = roletype->role; ebitmap_node_t *rnode; unsigned int i; ebitmap_for_each_bit(attr->roles, rnode, i) { struct cil_role *role = NULL; if (!ebitmap_get_bit(attr->roles, i)) { continue; } role = db->val_to_role[i]; rc = __cil_role_assign_types(role, type_datum); if (rc != SEPOL_OK) { goto exit; } } } else { struct cil_role *role = roletype->role; rc = __cil_role_assign_types(role, type_datum); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n"); return rc; } static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum) { struct cil_tree_node *node = datum->nodes->head->data; struct cil_role *role = NULL; struct cil_roleattribute *attr = NULL; if (user->roles == NULL) { user->roles = cil_malloc(sizeof(*user->roles)); ebitmap_init(user->roles); } if (node->flavor == CIL_ROLE) { role = (struct cil_role *)datum; if (ebitmap_set_bit(user->roles, role->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n"); goto exit; } } else if (node->flavor == CIL_ROLEATTRIBUTE) { attr = (struct cil_roleattribute *)datum; ebitmap_union(user->roles, attr->roles); } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_post_db_userrole_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; struct cil_block *blk = NULL; struct cil_userrole *userrole = NULL; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; struct cil_tree_node *user_node = NULL; struct cil_userattribute *u_attr = NULL; unsigned int i; struct cil_user *user = NULL; ebitmap_node_t *unode = NULL; switch (node->flavor) { case CIL_BLOCK: { blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_USERROLE: { userrole = node->data; user_datum = userrole->user; role_datum = userrole->role; user_node = user_datum->nodes->head->data; if (user_node->flavor == CIL_USERATTRIBUTE) { u_attr = userrole->user; ebitmap_for_each_bit(u_attr->users, unode, i) { if (!ebitmap_get_bit(u_attr->users, i)) { continue; } user = db->val_to_user[i]; rc = __cil_user_assign_roles(user, role_datum); if (rc != SEPOL_OK) { goto exit; } } } else { user = userrole->user; rc = __cil_user_assign_roles(user, role_datum); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n"); return rc; } static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db) { if (level->cats != NULL) { return __evaluate_cat_expression(level->cats, db); } return SEPOL_OK; } static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db) { int rc = SEPOL_OK; if (levelrange->low != NULL && levelrange->low->cats != NULL) { rc = __evaluate_cat_expression(levelrange->low->cats, db); if (rc != SEPOL_OK) { goto exit; } } if (levelrange->high != NULL && levelrange->high->cats != NULL) { rc = __evaluate_cat_expression(levelrange->high->cats, db); if (rc != SEPOL_OK) { goto exit; } } exit: return rc; } static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_CATSET: { struct cil_catset *catset = node->data; rc = __evaluate_cat_expression(catset->cats, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SENSCAT: { struct cil_senscat *senscat = node->data; rc = __evaluate_cat_expression(senscat->cats, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_LEVEL: { rc = __evaluate_level_expression(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_LEVELRANGE: { rc = __evaluate_levelrange_expression(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_USER: { struct cil_user *user = node->data; rc = __evaluate_level_expression(user->dftlevel, db); if (rc != SEPOL_OK) { goto exit; } rc = __evaluate_levelrange_expression(user->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSER: { struct cil_selinuxuser *selinuxuser = node->data; rc = __evaluate_levelrange_expression(selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_RANGETRANSITION: { struct cil_rangetransition *rangetrans = node->data; rc = __evaluate_levelrange_expression(rangetrans->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CONTEXT: { struct cil_context *context = node->data; rc = __evaluate_levelrange_expression(context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SIDCONTEXT: { struct cil_sidcontext *sidcontext = node->data; rc = __evaluate_levelrange_expression(sidcontext->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_FILECON: { struct cil_filecon *filecon = node->data; if (filecon->context) { rc = __evaluate_levelrange_expression(filecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } } break; } case CIL_IBPKEYCON: { struct cil_ibpkeycon *ibpkeycon = node->data; rc = __evaluate_levelrange_expression(ibpkeycon->context->range, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_IBENDPORTCON: { struct cil_ibendportcon *ibendportcon = node->data; rc = __evaluate_levelrange_expression(ibendportcon->context->range, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_PORTCON: { struct cil_portcon *portcon = node->data; rc = __evaluate_levelrange_expression(portcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_NODECON: { struct cil_nodecon *nodecon = node->data; rc = __evaluate_levelrange_expression(nodecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_GENFSCON: { struct cil_genfscon *genfscon = node->data; rc = __evaluate_levelrange_expression(genfscon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_NETIFCON: { struct cil_netifcon *netifcon = node->data; rc = __evaluate_levelrange_expression(netifcon->if_context->range, db); if (rc != SEPOL_OK) { goto exit; } rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_PIRQCON: { struct cil_pirqcon *pirqcon = node->data; rc = __evaluate_levelrange_expression(pirqcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_IOMEMCON: { struct cil_iomemcon *iomemcon = node->data; rc = __evaluate_levelrange_expression(iomemcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_IOPORTCON: { struct cil_ioportcon *ioportcon = node->data; rc = __evaluate_levelrange_expression(ioportcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_PCIDEVICECON: { struct cil_pcidevicecon *pcidevicecon = node->data; rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_DEVICETREECON: { struct cil_devicetreecon *devicetreecon = node->data; rc = __evaluate_levelrange_expression(devicetreecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_FSUSE: { struct cil_fsuse *fsuse = node->data; rc = __evaluate_levelrange_expression(fsuse->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } default: break; } return SEPOL_OK; exit: return rc; } struct perm_to_list { enum cil_flavor flavor; ebitmap_t *perms; struct cil_list *new_list; }; static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct perm_to_list *perm_args = (struct perm_to_list *)args; ebitmap_t *perms = perm_args->perms; struct cil_list *new_list = perm_args->new_list; struct cil_perm *perm = (struct cil_perm *)d; unsigned int value = perm->value; if (!ebitmap_get_bit(perms, value)) { return SEPOL_OK; } cil_list_append(new_list, CIL_DATUM, d); return SEPOL_OK; } static int __evaluate_perm_expression(struct cil_list *perms, enum cil_flavor flavor, symtab_t *class_symtab, symtab_t *common_symtab, unsigned int num_perms, struct cil_list **new_list, struct cil_db *db) { int rc = SEPOL_ERR; struct perm_to_list args; ebitmap_t bitmap; if (cil_verify_is_list(perms, CIL_PERM)) { return SEPOL_OK; } ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db); if (rc != SEPOL_OK) { ebitmap_destroy(&bitmap); goto exit; } cil_list_init(new_list, flavor); args.flavor = flavor; args.perms = &bitmap; args.new_list = *new_list; cil_symtab_map(class_symtab, __perm_bits_to_list, &args); if (common_symtab != NULL) { cil_symtab_map(common_symtab, __perm_bits_to_list, &args); } ebitmap_destroy(&bitmap); return SEPOL_OK; exit: return rc; } static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_class *class = cp->class; struct cil_class *common = class->common; symtab_t *common_symtab = NULL; struct cil_list *new_list = NULL; if (common) { common_symtab = &common->perms; } rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db); if (rc != SEPOL_OK) { goto exit; } if (new_list == NULL) { return SEPOL_OK; } cil_list_destroy(&cp->perms, CIL_FALSE); cp->perms = new_list; return SEPOL_OK; exit: return rc; } static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __evaluate_classperms(cp, db); if (rc != SEPOL_OK) { goto exit; } } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __evaluate_classperms_list(cmp->classperms, db); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __evaluate_classperms_list(cp->classperms, db); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } struct class_map_args { struct cil_db *db; int rc; }; static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct class_map_args *map_args = args; struct cil_perm *cmp = (struct cil_perm *)d; int rc = __evaluate_classperms_list(cmp->classperms, map_args->db); if (rc != SEPOL_OK) { map_args->rc = rc; } return SEPOL_OK; } static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db) { struct class_map_args map_args; map_args.db = db; map_args.rc = SEPOL_OK; cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args); return map_args.rc; } static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_MAP_CLASS: { rc = __evaluate_map_class(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CLASSPERMISSION: { struct cil_classpermission *cp = node->data; rc = __evaluate_classperms_list(cp->classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_AVRULE: { struct cil_avrule *avrule = node->data; rc = __evaluate_classperms_list(avrule->perms.classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: { struct cil_constrain *constrain = node->data; rc = __evaluate_classperms_list(constrain->classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } default: break; } return SEPOL_OK; exit: return rc; } static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_list_item *li = extra_args; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; } else if (node->flavor == li->flavor) { if (node->data == li->data) { char *path = cil_tree_get_cil_path(node); cil_log(CIL_WARN, " at %s:%d\n", path, node->line); } } return SEPOL_OK; } static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str) { uint32_t count = sort->count; uint32_t i, j = 0, removed = 0; int rc = SEPOL_OK; if (count < 2) { return SEPOL_OK; } qsort(sort->array, sort->count, sizeof(sort->array), compar); for (i=1; iarray[i], &sort->array[j]) != 0) { j++; } else { removed++; if (!db->multiple_decls || concompar(&sort->array[i], &sort->array[j]) != 0) { struct cil_list_item li; int rc2; cil_log(CIL_WARN, "Found conflicting %s rules\n", flavor_str); rc = SEPOL_ERR; li.flavor = flavor; li.data = sort->array[i]; rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, NULL, NULL, &li); if (rc2 != SEPOL_OK) goto exit; li.data = sort->array[j]; rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, NULL, NULL, &li); if (rc2 != SEPOL_OK) goto exit; } } if (i != j) { sort->array[j] = sort->array[i]; } } sort->count = count - removed; exit: return rc; } static int cil_post_db(struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure during cil databse count helper\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure during cil database array helper\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_neverallow_attr_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to mark attributes used by generated attributes used in neverallow rules\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to create attribute bitmaps\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed during roletype association\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed during userrole association\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to evaluate category expressions\n"); goto exit; } rc = __cil_post_process_context_rules(db->netifcon, cil_post_netifcon_compare, cil_post_netifcon_context_compare, db, CIL_NETIFCON, CIL_KEY_NETIFCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing netifcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->genfscon, cil_post_genfscon_compare, cil_post_genfscon_context_compare, db, CIL_GENFSCON, CIL_KEY_GENFSCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing genfscon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ibpkeycon, cil_post_ibpkeycon_compare, cil_post_ibpkeycon_context_compare, db, CIL_IBPKEYCON, CIL_KEY_IBPKEYCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ibpkeycon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ibendportcon, cil_post_ibendportcon_compare, cil_post_ibendportcon_context_compare, db, CIL_IBENDPORTCON, CIL_KEY_IBENDPORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ibendportcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->portcon, cil_post_portcon_compare, cil_post_portcon_context_compare, db, CIL_PORTCON, CIL_KEY_PORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing portcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->nodecon, cil_post_nodecon_compare, cil_post_nodecon_context_compare, db, CIL_NODECON, CIL_KEY_NODECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing nodecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->fsuse, cil_post_fsuse_compare, cil_post_fsuse_context_compare, db, CIL_FSUSE, CIL_KEY_FSUSE); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing fsuse rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->filecon, cil_post_filecon_compare, cil_post_filecon_context_compare, db, CIL_FILECON, CIL_KEY_FILECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing filecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->iomemcon, cil_post_iomemcon_compare, cil_post_iomemcon_context_compare, db, CIL_IOMEMCON, CIL_KEY_IOMEMCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing iomemcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ioportcon, cil_post_ioportcon_compare, cil_post_ioportcon_context_compare, db, CIL_IOPORTCON, CIL_KEY_IOPORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ioportcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->pcidevicecon, cil_post_pcidevicecon_compare, cil_post_pcidevicecon_context_compare, db, CIL_PCIDEVICECON, CIL_KEY_PCIDEVICECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing pcidevicecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->devicetreecon, cil_post_devicetreecon_compare, cil_post_devicetreecon_context_compare, db, CIL_DEVICETREECON, CIL_KEY_DEVICETREECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing devicetreecon rules\n"); goto exit; } exit: return rc; } static int cil_post_verify(struct cil_db *db) { int rc = SEPOL_ERR; int avrule_cnt = 0; int handleunknown = -1; int mls = -1; int nseuserdflt = 0; int pass = 0; struct cil_args_verify extra_args; struct cil_complex_symtab csymtab; cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE); extra_args.db = db; extra_args.csymtab = &csymtab; extra_args.avrule_cnt = &avrule_cnt; extra_args.handleunknown = &handleunknown; extra_args.mls = &mls; extra_args.nseuserdflt = &nseuserdflt; extra_args.pass = &pass; for (pass = 0; pass < 2; pass++) { rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } } if (db->handle_unknown == -1) { if (handleunknown == -1) { db->handle_unknown = SEPOL_DENY_UNKNOWN; } else { db->handle_unknown = handleunknown; } } if (db->mls == -1) { if (mls == -1) { db->mls = CIL_FALSE; } else { db->mls = mls; } } if (avrule_cnt == 0) { cil_log(CIL_ERR, "Policy must include at least one avrule\n"); rc = SEPOL_ERR; goto exit; } if (nseuserdflt > 1) { cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt); rc = SEPOL_ERR; goto exit; } exit: cil_complex_symtab_destroy(&csymtab); return rc; } static int cil_pre_verify(struct cil_db *db) { int rc = SEPOL_ERR; struct cil_args_verify extra_args; extra_args.db = db; rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } exit: return rc; } int cil_post_process(struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_pre_verify(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } rc = cil_post_db(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed post db handling\n"); goto exit; } rc = cil_post_verify(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } exit: return rc; } libsepol/cil/src/cil_post.h0100644 0000000 0000000 00000004466 13756670065 014772 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_POST_H_ #define CIL_POST_H_ struct fc_data { int meta; int stem_len; int str_len; }; void cil_post_fc_fill_data(struct fc_data *fc, char *path); int cil_post_filecon_compare(const void *a, const void *b); int cil_post_ibpkeycon_compare(const void *a, const void *b); int cil_post_portcon_compare(const void *a, const void *b); int cil_post_ibendportcon_compare(const void *a, const void *b); int cil_post_genfscon_compare(const void *a, const void *b); int cil_post_netifcon_compare(const void *a, const void *b); int cil_post_nodecon_compare(const void *a, const void *b); int cil_post_fsuse_compare(const void *a, const void *b); int cil_post_context_sort(struct cil_db *db); int cil_post_process(struct cil_db *db); #endif libsepol/cil/src/cil_reset_ast.c0100644 0000000 0000000 00000033350 13756670065 015763 0ustar000000000 0000000 #include "cil_internal.h" #include "cil_log.h" #include "cil_list.h" #include "cil_symtab.h" static inline void cil_reset_classperms_list(struct cil_list *cp_list); static inline void cil_reset_level(struct cil_level *level); static inline void cil_reset_levelrange(struct cil_levelrange *levelrange); static inline void cil_reset_context(struct cil_context *context); static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_perm *perm = (struct cil_perm *)d; perm->value -= *((int *)args); return SEPOL_OK; } static void cil_reset_class(struct cil_class *class) { if (class->common != NULL) { struct cil_class *common = class->common; cil_symtab_map(&class->perms, __class_reset_perm_values, &common->num_perms); /* during a re-resolve, we need to reset the common, so a classcommon * statement isn't seen as a duplicate */ class->num_perms -= common->num_perms; class->common = NULL; /* Must make this NULL or there will be an error when re-resolving */ } class->ordered = CIL_FALSE; } static void cil_reset_perm(struct cil_perm *perm) { cil_reset_classperms_list(perm->classperms); } static inline void cil_reset_classperms(struct cil_classperms *cp) { if (cp == NULL) { return; } cil_list_destroy(&cp->perms, CIL_FALSE); } static void cil_reset_classpermission(struct cil_classpermission *cp) { if (cp == NULL) { return; } cil_reset_classperms_list(cp->classperms); } static void cil_reset_classperms_set(struct cil_classperms_set *cp_set) { cil_reset_classpermission(cp_set->set); } static inline void cil_reset_classperms_list(struct cil_list *cp_list) { struct cil_list_item *curr; if (cp_list == NULL) { return; } cil_list_for_each(curr, cp_list) { if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP */ cil_reset_classperms(curr->data); } else if (curr->flavor == CIL_CLASSPERMS_SET) { /* SET */ cil_reset_classperms_set(curr->data); } } } static void cil_reset_classpermissionset(struct cil_classpermissionset *cps) { cil_reset_classperms_list(cps->classperms); } static void cil_reset_classmapping(struct cil_classmapping *cm) { cil_reset_classperms_list(cm->classperms); } static void cil_reset_alias(struct cil_alias *alias) { /* reset actual to NULL during a re-resolve */ alias->actual = NULL; } static void cil_reset_user(struct cil_user *user) { /* reset the bounds to NULL during a re-resolve */ user->bounds = NULL; user->dftlevel = NULL; user->range = NULL; } static void cil_reset_userattr(struct cil_userattribute *attr) { struct cil_list_item *expr = NULL; struct cil_list_item *next = NULL; /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a userattribute statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ expr = attr->expr_list->head; while (expr != NULL) { next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } } static void cil_reset_userattributeset(struct cil_userattributeset *uas) { cil_list_destroy(&uas->datum_expr, CIL_FALSE); } static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser) { if (selinuxuser->range_str == NULL) { cil_reset_levelrange(selinuxuser->range); } } static void cil_reset_role(struct cil_role *role) { /* reset the bounds to NULL during a re-resolve */ role->bounds = NULL; } static void cil_reset_roleattr(struct cil_roleattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributeroles statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } } static void cil_reset_roleattributeset(struct cil_roleattributeset *ras) { cil_list_destroy(&ras->datum_expr, CIL_FALSE); } static void cil_reset_type(struct cil_type *type) { /* reset the bounds to NULL during a re-resolve */ type->bounds = NULL; } static void cil_reset_typeattr(struct cil_typeattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributetypes statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } attr->used = CIL_FALSE; attr->keep = CIL_FALSE; } static void cil_reset_typeattributeset(struct cil_typeattributeset *tas) { cil_list_destroy(&tas->datum_expr, CIL_FALSE); } static void cil_reset_avrule(struct cil_avrule *rule) { cil_reset_classperms_list(rule->perms.classperms); } static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans->range_str == NULL) { cil_reset_levelrange(rangetrans->range); } } static void cil_reset_sens(struct cil_sens *sens) { /* during a re-resolve, we need to reset the categories associated with * this sensitivity from a (sensitivitycategory) statement */ cil_list_destroy(&sens->cats_list, CIL_FALSE); sens->ordered = CIL_FALSE; } static void cil_reset_cat(struct cil_cat *cat) { cat->ordered = CIL_FALSE; } static inline void cil_reset_cats(struct cil_cats *cats) { if (cats != NULL) { cats->evaluated = CIL_FALSE; cil_list_destroy(&cats->datum_expr, CIL_FALSE); } } static void cil_reset_senscat(struct cil_senscat *senscat) { cil_reset_cats(senscat->cats); } static void cil_reset_catset(struct cil_catset *catset) { cil_reset_cats(catset->cats); } static inline void cil_reset_level(struct cil_level *level) { cil_reset_cats(level->cats); } static inline void cil_reset_levelrange(struct cil_levelrange *levelrange) { if (levelrange->low_str == NULL) { cil_reset_level(levelrange->low); } if (levelrange->high_str == NULL) { cil_reset_level(levelrange->high); } } static inline void cil_reset_userlevel(struct cil_userlevel *userlevel) { if (userlevel->level_str == NULL) { cil_reset_level(userlevel->level); } } static inline void cil_reset_userrange(struct cil_userrange *userrange) { if (userrange->range_str == NULL) { cil_reset_levelrange(userrange->range); } } static inline void cil_reset_context(struct cil_context *context) { if (context->range_str == NULL) { cil_reset_levelrange(context->range); } } static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext) { if (sidcontext->context_str == NULL) { cil_reset_context(sidcontext->context); } } static void cil_reset_filecon(struct cil_filecon *filecon) { if (filecon->context_str == NULL && filecon->context != NULL) { cil_reset_context(filecon->context); } } static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) { if (!ibpkeycon->context_str) cil_reset_context(ibpkeycon->context); } static void cil_reset_portcon(struct cil_portcon *portcon) { if (portcon->context_str == NULL) { cil_reset_context(portcon->context); } } static void cil_reset_nodecon(struct cil_nodecon *nodecon) { if (nodecon->context_str == NULL) { cil_reset_context(nodecon->context); } } static void cil_reset_genfscon(struct cil_genfscon *genfscon) { if (genfscon->context_str == NULL) { cil_reset_context(genfscon->context); } } static void cil_reset_netifcon(struct cil_netifcon *netifcon) { if (netifcon->if_context_str == NULL) { cil_reset_context(netifcon->if_context); } if (netifcon->packet_context_str == NULL) { cil_reset_context(netifcon->packet_context); } } static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon) { if (!ibendportcon->context_str) { cil_reset_context(ibendportcon->context); } } static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon->context_str == NULL) { cil_reset_context(pirqcon->context); } } static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon->context_str == NULL) { cil_reset_context(iomemcon->context); } } static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon->context_str == NULL) { cil_reset_context(ioportcon->context); } } static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon->context_str == NULL) { cil_reset_context(pcidevicecon->context); } } static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon->context_str == NULL) { cil_reset_context(devicetreecon->context); } } static void cil_reset_fsuse(struct cil_fsuse *fsuse) { if (fsuse->context_str == NULL) { cil_reset_context(fsuse->context); } } static void cil_reset_sid(struct cil_sid *sid) { /* reset the context to NULL during a re-resolve */ sid->context = NULL; sid->ordered = CIL_FALSE; } static void cil_reset_constrain(struct cil_constrain *con) { cil_reset_classperms_list(con->classperms); cil_list_destroy(&con->datum_expr, CIL_FALSE); } static void cil_reset_validatetrans(struct cil_validatetrans *vt) { cil_list_destroy(&vt->datum_expr, CIL_FALSE); } static void cil_reset_default(struct cil_default *def) { cil_list_destroy(&def->class_datums, CIL_FALSE); } static void cil_reset_defaultrange(struct cil_defaultrange *def) { cil_list_destroy(&def->class_datums, CIL_FALSE); } static void cil_reset_booleanif(struct cil_booleanif *bif) { cil_list_destroy(&bif->datum_expr, CIL_FALSE); } int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args) { switch (node->flavor) { case CIL_CLASS: cil_reset_class(node->data); break; case CIL_PERM: case CIL_MAP_PERM: cil_reset_perm(node->data); break; case CIL_CLASSPERMISSION: cil_reset_classpermission(node->data); break; case CIL_CLASSPERMISSIONSET: cil_reset_classpermissionset(node->data); break; case CIL_CLASSMAPPING: cil_reset_classmapping(node->data); break; case CIL_TYPEALIAS: case CIL_SENSALIAS: case CIL_CATALIAS: cil_reset_alias(node->data); break; case CIL_USERRANGE: cil_reset_userrange(node->data); break; case CIL_USERLEVEL: cil_reset_userlevel(node->data); break; case CIL_USER: cil_reset_user(node->data); break; case CIL_USERATTRIBUTE: cil_reset_userattr(node->data); break; case CIL_USERATTRIBUTESET: cil_reset_userattributeset(node->data); break; case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSER: cil_reset_selinuxuser(node->data); break; case CIL_ROLE: cil_reset_role(node->data); break; case CIL_ROLEATTRIBUTE: cil_reset_roleattr(node->data); break; case CIL_ROLEATTRIBUTESET: cil_reset_roleattributeset(node->data); break; case CIL_TYPE: cil_reset_type(node->data); break; case CIL_TYPEATTRIBUTE: cil_reset_typeattr(node->data); break; case CIL_TYPEATTRIBUTESET: cil_reset_typeattributeset(node->data); break; case CIL_RANGETRANSITION: cil_reset_rangetransition(node->data); break; case CIL_AVRULE: cil_reset_avrule(node->data); break; case CIL_SENS: cil_reset_sens(node->data); break; case CIL_CAT: cil_reset_cat(node->data); break; case CIL_SENSCAT: cil_reset_senscat(node->data); break; case CIL_CATSET: cil_reset_catset(node->data); break; case CIL_LEVEL: cil_reset_level(node->data); break; case CIL_LEVELRANGE: cil_reset_levelrange(node->data); break; case CIL_CONTEXT: cil_reset_context(node->data); break; case CIL_SIDCONTEXT: cil_reset_sidcontext(node->data); break; case CIL_FILECON: cil_reset_filecon(node->data); break; case CIL_IBPKEYCON: cil_reset_ibpkeycon(node->data); break; case CIL_IBENDPORTCON: cil_reset_ibendportcon(node->data); break; case CIL_PORTCON: cil_reset_portcon(node->data); break; case CIL_NODECON: cil_reset_nodecon(node->data); break; case CIL_GENFSCON: cil_reset_genfscon(node->data); break; case CIL_NETIFCON: cil_reset_netifcon(node->data); break; case CIL_PIRQCON: cil_reset_pirqcon(node->data); break; case CIL_IOMEMCON: cil_reset_iomemcon(node->data); break; case CIL_IOPORTCON: cil_reset_ioportcon(node->data); break; case CIL_PCIDEVICECON: cil_reset_pcidevicecon(node->data); break; case CIL_DEVICETREECON: cil_reset_devicetreecon(node->data); break; case CIL_FSUSE: cil_reset_fsuse(node->data); break; case CIL_SID: cil_reset_sid(node->data); break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: cil_reset_constrain(node->data); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: cil_reset_validatetrans(node->data); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: cil_reset_default(node->data); break; case CIL_DEFAULTRANGE: cil_reset_defaultrange(node->data); break; case CIL_BOOLEANIF: cil_reset_booleanif(node->data); break; case CIL_TUNABLEIF: case CIL_CALL: break; /* Not effected by optional block disabling */ case CIL_MACRO: case CIL_SIDORDER: case CIL_CLASSORDER: case CIL_CATORDER: case CIL_SENSITIVITYORDER: case CIL_EXPANDTYPEATTRIBUTE: break; /* Nothing to reset */ default: break; } return SEPOL_OK; } int cil_reset_ast(struct cil_tree_node *current) { int rc = SEPOL_ERR; rc = cil_tree_walk(current, __cil_reset_node, NULL, NULL, NULL); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to reset AST\n"); return SEPOL_ERR; } return SEPOL_OK; } libsepol/cil/src/cil_reset_ast.h0100644 0000000 0000000 00000000233 13756670065 015762 0ustar000000000 0000000 #ifndef CIL_RESET_AST_H_ #define CIL_RESET_AST_H_ #include "cil_tree.h" int cil_reset_ast(struct cil_tree_node *current); #endif /* CIL_RESET_AST_H_ */ libsepol/cil/src/cil_resolve_ast.c0100644 0000000 0000000 00000325632 13756670065 016327 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_build_ast.h" #include "cil_resolve_ast.h" #include "cil_reset_ast.h" #include "cil_copy_ast.h" #include "cil_verify.h" #include "cil_strpool.h" #include "cil_symtab.h" struct cil_args_resolve { struct cil_db *db; enum cil_pass pass; uint32_t *changed; char *last_resolved_name; struct cil_tree_node *optstack; struct cil_tree_node *boolif; struct cil_tree_node *macro; struct cil_tree_node *blockstack; struct cil_list *sidorder_lists; struct cil_list *classorder_lists; struct cil_list *unordered_classorder_lists; struct cil_list *catorder_lists; struct cil_list *sensitivityorder_lists; struct cil_list *in_list; }; static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) { /* Currently only used for typetransition file names. But could be used for any string that is passed as a parameter. */ struct cil_tree_node *parent = ast_node->parent; struct cil_macro *macro = NULL; struct cil_name *name; symtab_t *symtab; enum cil_sym_index sym_index; struct cil_symtab_datum *datum = NULL; cil_flavor_to_symtab_index(CIL_NAME, &sym_index); symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { return (struct cil_name *)datum; } if (parent->flavor == CIL_CALL) { struct cil_call *call = parent->data; macro = call->macro; } else if (parent->flavor == CIL_MACRO) { macro = parent->data; } if (macro != NULL) { struct cil_list_item *item; cil_list_for_each(item, macro->params) { if (((struct cil_param*)item->data)->str == key) { return NULL; } } } cil_name_init(&name); cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node); cil_list_append(db->names, CIL_NAME, name); return name; } static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, struct cil_list *perm_strs, struct cil_list **perm_datums, enum cil_flavor class_flavor) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_init(perm_datums, perm_strs->flavor); cil_list_for_each(curr, perm_strs) { if (curr->flavor == CIL_LIST) { struct cil_list *sub_list; rc = __cil_resolve_perms(class_symtab, common_symtab, curr->data, &sub_list, class_flavor); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve permission list\n"); goto exit; } cil_list_append(*perm_datums, CIL_LIST, sub_list); } else if (curr->flavor == CIL_STRING) { struct cil_symtab_datum *perm_datum = NULL; rc = cil_symtab_get_datum(class_symtab, curr->data, &perm_datum); if (rc == SEPOL_ENOENT) { if (common_symtab) { rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum); } } if (rc != SEPOL_OK) { struct cil_list *empty_list; if (class_flavor == CIL_MAP_CLASS) { cil_log(CIL_ERR, "Failed to resolve permission %s for map class\n", (char*)curr->data); goto exit; } cil_log(CIL_WARN, "Failed to resolve permission %s\n", (char*)curr->data); /* Use an empty list to represent unknown perm */ cil_list_init(&empty_list, perm_strs->flavor); cil_list_append(*perm_datums, CIL_LIST, empty_list); } else { cil_list_append(*perm_datums, CIL_DATUM, perm_datum); } } else { cil_list_append(*perm_datums, curr->flavor, curr->data); } } return SEPOL_OK; exit: return rc; } int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; symtab_t *common_symtab = NULL; struct cil_class *class; rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; } class = (struct cil_class *)datum; if (class->common != NULL) { common_symtab = &class->common->perms; } cp->class = class; rc = __cil_resolve_perms(&class->perms, common_symtab, cp->perm_strs, &cp->perms, FLAVOR(datum)); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, void *extra_args) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; } cp_set->set = (struct cil_classpermission*)datum; /* This could be an anonymous classpermission */ if (datum->name == NULL) { rc = cil_resolve_classperms_list(current, cp_set->set->classperms, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, cp_list) { if (curr->flavor == CIL_CLASSPERMS) { rc = cil_resolve_classperms(current, curr->data, extra_args); if (rc != SEPOL_OK) { goto exit; } } else { rc = cil_resolve_classperms_set(current, curr->data, extra_args); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; struct cil_list_item *curr; struct cil_symtab_datum *datum; struct cil_classpermission *cp; rc = cil_resolve_name(current, cps->set_str, CIL_SYM_CLASSPERMSETS, args, &datum); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_classperms_list(current, cps->classperms, extra_args); if (rc != SEPOL_OK) { goto exit; } cp = (struct cil_classpermission *)datum; if (cp->classperms == NULL) { cil_list_init(&cp->classperms, CIL_CLASSPERMS); } cil_list_for_each(curr, cps->classperms) { cil_list_append(cp->classperms, curr->flavor, curr->data); } return SEPOL_OK; exit: return rc; } void cil_type_used(struct cil_symtab_datum *datum, int used) { struct cil_typeattribute *attr = NULL; if (FLAVOR(datum) == CIL_TYPEATTRIBUTE) { attr = (struct cil_typeattribute*)datum; attr->used |= used; if ((attr->used & CIL_ATTR_EXPAND_TRUE) && (attr->used & CIL_ATTR_EXPAND_FALSE)) { cil_log(CIL_WARN, "Conflicting use of expandtypeattribute. " "Expandtypeattribute was set to both true or false for %s. " "Resolving to false. \n", attr->datum.name); attr->used &= ~CIL_ATTR_EXPAND_TRUE; } } } int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, void *extra_args) { struct cil_symtab_datum *obj_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); if (rc != SEPOL_OK) { goto exit; } permx->obj = (struct cil_class*)obj_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_db *db = NULL; struct cil_avrule *rule = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; struct cil_symtab_datum *permx_datum = NULL; int used; int rc = SEPOL_ERR; if (args != NULL) { db = args->db; } rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, args, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; if (rule->tgt_str == CIL_KEY_SELF) { rule->tgt = db->selftype; } else { rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; used = (rule->rule_kind == CIL_AVRULE_NEVERALLOW) ? CIL_ATTR_NEVERALLOW : CIL_ATTR_AVRULE; cil_type_used(src_datum, used); /* src not used if tgt is self */ cil_type_used(tgt_datum, used); } if (!rule->is_extended) { rc = cil_resolve_classperms_list(current, rule->perms.classperms, extra_args); if (rc != SEPOL_OK) { goto exit; } } else { if (rule->perms.x.permx_str != NULL) { rc = cil_resolve_name(current, rule->perms.x.permx_str, CIL_SYM_PERMX, args, &permx_datum); if (rc != SEPOL_OK) { goto exit; } rule->perms.x.permx = (struct cil_permissionx*)permx_datum; } else { rc = cil_resolve_permissionx(current, rule->perms.x.permx, extra_args); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args) { struct cil_type_rule *rule = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; struct cil_symtab_datum *obj_datum = NULL; struct cil_symtab_datum *result_datum = NULL; struct cil_tree_node *result_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, extra_args, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); if (rc != SEPOL_OK) { goto exit; } rule->obj = (struct cil_class*)obj_datum; rc = cil_resolve_name(current, rule->result_str, CIL_SYM_TYPES, extra_args, &result_datum); if (rc != SEPOL_OK) { goto exit; } result_node = result_datum->nodes->head->data; if (result_node->flavor != CIL_TYPE) { cil_log(CIL_ERR, "Type rule result must be a type [%d]\n",result_node->flavor); rc = SEPOL_ERR; goto exit; } rule->result = result_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args) { struct cil_typeattributeset *attrtypes = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_typeattribute *attr = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, attrtypes->attr_str, CIL_SYM_TYPES, extra_args, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = attr_datum->nodes->head->data; if (attr_node->flavor != CIL_TYPEATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute type not an attribute\n"); goto exit; } attr = (struct cil_typeattribute*)attr_datum; rc = cil_resolve_expr(CIL_TYPEATTRIBUTESET, attrtypes->str_expr, &attrtypes->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr); if (rc != SEPOL_OK) { goto exit; } if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE); } cil_list_append(attr->expr_list, CIL_LIST, attrtypes->datum_expr); return SEPOL_OK; exit: return rc; } int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void *extra_args) { struct cil_expandtypeattribute *expandattr = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_list_item *curr; int used; int rc = SEPOL_ERR; cil_list_init(&expandattr->attr_datums, CIL_TYPE); cil_list_for_each(curr, expandattr->attr_strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_TYPES, extra_args, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = attr_datum->nodes->head->data; if (attr_node->flavor != CIL_TYPEATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute type not an attribute\n"); goto exit; } used = expandattr->expand ? CIL_ATTR_EXPAND_TRUE : CIL_ATTR_EXPAND_FALSE; cil_type_used(attr_datum, used); cil_list_append(expandattr->attr_datums, CIL_TYPE, attr_datum); } return SEPOL_OK; exit: return rc; } int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor alias_flavor) { int rc = SEPOL_ERR; enum cil_sym_index sym_index; struct cil_aliasactual *aliasactual = current->data; struct cil_symtab_datum *alias_datum = NULL; struct cil_symtab_datum *actual_datum = NULL; struct cil_alias *alias; rc = cil_flavor_to_symtab_index(flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_name_keep_aliases(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum); if (rc != SEPOL_OK) { goto exit; } if (NODE(alias_datum)->flavor != alias_flavor) { cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, extra_args, &actual_datum); if (rc != SEPOL_OK) { goto exit; } if (NODE(actual_datum)->flavor != flavor && NODE(actual_datum)->flavor != alias_flavor) { cil_log(CIL_ERR, "%s is a %s, but aliases a %s\n", alias_datum->name, cil_node_to_string(NODE(alias_datum)), cil_node_to_string(NODE(actual_datum))); rc = SEPOL_ERR; goto exit; } alias = (struct cil_alias *)alias_datum; if (alias->actual != NULL) { cil_log(CIL_ERR, "%s %s cannot bind more than one value\n", cil_node_to_string(NODE(alias_datum)), alias_datum->name); rc = SEPOL_ERR; goto exit; } alias->actual = actual_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor flavor) { struct cil_alias *alias = current->data; struct cil_alias *a1 = current->data; struct cil_alias *a2 = current->data; struct cil_tree_node *a1_node = NULL; int steps = 0; int limit = 2; if (alias->actual == NULL) { cil_tree_log(current, CIL_ERR, "Alias declared but not used"); return SEPOL_ERR; } a1_node = a1->datum.nodes->head->data; while (flavor != a1_node->flavor) { a1 = a1->actual; a1_node = a1->datum.nodes->head->data; steps += 1; if (a1 == a2) { cil_log(CIL_ERR, "Circular alias found: %s ", a1->datum.name); a1 = a1->actual; while (a1 != a2) { cil_log(CIL_ERR, "%s ", a1->datum.name); a1 = a1->actual; } cil_log(CIL_ERR,"\n"); return SEPOL_ERR; } if (steps == limit) { steps = 0; limit *= 2; a2 = a1; } } alias->actual = a1; return SEPOL_OK; } int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args) { struct cil_typepermissive *typeperm = current->data; struct cil_symtab_datum *type_datum = NULL; struct cil_tree_node *type_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, typeperm->type_str, CIL_SYM_TYPES, extra_args, &type_datum); if (rc != SEPOL_OK) { goto exit; } type_node = type_datum->nodes->head->data; if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) { cil_log(CIL_ERR, "Typepermissive must be a type or type alias\n"); rc = SEPOL_ERR; goto exit; } typeperm->type = type_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_nametypetransition *nametypetrans = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; struct cil_symtab_datum *obj_datum = NULL; struct cil_symtab_datum *name_datum = NULL; struct cil_symtab_datum *result_datum = NULL; struct cil_tree_node *result_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, nametypetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->src = src_datum; rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->tgt = tgt_datum; rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->obj = (struct cil_class*)obj_datum; nametypetrans->name = __cil_insert_name(args->db, nametypetrans->name_str, current); if (nametypetrans->name == NULL) { rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_NAMES, extra_args, &name_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->name = (struct cil_name *)name_datum; } rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, extra_args, &result_datum); if (rc != SEPOL_OK) { goto exit; } result_node = result_datum->nodes->head->data; if (result_node->flavor != CIL_TYPE && result_node->flavor != CIL_TYPEALIAS) { cil_log(CIL_ERR, "typetransition result is not a type or type alias\n"); rc = SEPOL_ERR; goto exit; } nametypetrans->result = result_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args) { struct cil_rangetransition *rangetrans = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *exec_datum = NULL; struct cil_symtab_datum *obj_datum = NULL; struct cil_symtab_datum *range_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, rangetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->src = src_datum; rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, extra_args, &exec_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->exec = exec_datum; rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->obj = (struct cil_class*)obj_datum; if (rangetrans->range_str != NULL) { rc = cil_resolve_name(current, rangetrans->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->range = (struct cil_levelrange*)range_datum; /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/ if (rangetrans->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, rangetrans->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else { rc = cil_resolve_levelrange(current, rangetrans->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int __class_update_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_perm *perm = (struct cil_perm *)d; perm->value += *((int *)args); return SEPOL_OK; } int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) { struct cil_class *class = NULL; struct cil_class *common = NULL; struct cil_classcommon *clscom = current->data; struct cil_symtab_datum *class_datum = NULL; struct cil_symtab_datum *common_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, clscom->class_str, CIL_SYM_CLASSES, extra_args, &class_datum); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, extra_args, &common_datum); if (rc != SEPOL_OK) { goto exit; } class = (struct cil_class *)class_datum; common = (struct cil_class *)common_datum; if (class->common != NULL) { cil_log(CIL_ERR, "class cannot be associeated with more than one common\n"); rc = SEPOL_ERR; goto exit; } class->common = common; cil_symtab_map(&class->perms, __class_update_perm_values, &common->num_perms); class->num_perms += common->num_perms; if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name); goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_classmapping *mapping = current->data; struct cil_class *map = NULL; struct cil_perm *mp = NULL; struct cil_symtab_datum *datum = NULL; struct cil_list_item *curr; rc = cil_resolve_name(current, mapping->map_class_str, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; } map = (struct cil_class*)datum; rc = cil_symtab_get_datum(&map->perms, mapping->map_perm_str, &datum); if (rc != SEPOL_OK) { goto exit; } mp = (struct cil_perm*)datum; rc = cil_resolve_classperms_list(current, mapping->classperms, extra_args); if (rc != SEPOL_OK) { goto exit; } if (mp->classperms == NULL) { cil_list_init(&mp->classperms, CIL_CLASSPERMS); } cil_list_for_each(curr, mapping->classperms) { cil_list_append(mp->classperms, curr->flavor, curr->data); } return SEPOL_OK; exit: return rc; } int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args) { struct cil_userrole *userrole = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, userrole->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } userrole->user = (struct cil_user*)user_datum; rc = cil_resolve_name(current, userrole->role_str, CIL_SYM_ROLES, extra_args, &role_datum); if (rc != SEPOL_OK) { goto exit; } userrole->role = role_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) { struct cil_userlevel *usrlvl = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *lvl_datum = NULL; struct cil_user *user = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = user_datum->nodes->head->data; if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userlevel must be a user\n"); rc = SEPOL_ERR; goto exit; } user = (struct cil_user*)user_datum; if (usrlvl->level_str != NULL) { rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, extra_args, &lvl_datum); if (rc != SEPOL_OK) { goto exit; } usrlvl->level = (struct cil_level*)lvl_datum; user->dftlevel = usrlvl->level; /* This could still be an anonymous level even if level_str is set, if level_str is a param_str*/ if (user->dftlevel->datum.name == NULL) { rc = cil_resolve_level(current, user->dftlevel, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (usrlvl->level != NULL) { rc = cil_resolve_level(current, usrlvl->level, extra_args); if (rc != SEPOL_OK) { goto exit; } user->dftlevel = usrlvl->level; } return SEPOL_OK; exit: return rc; } int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) { struct cil_userrange *userrange = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *range_datum = NULL; struct cil_user *user = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = user_datum->nodes->head->data; if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } user = (struct cil_user*)user_datum; if (userrange->range_str != NULL) { rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum); if (rc != SEPOL_OK) { goto exit; } userrange->range = (struct cil_levelrange*)range_datum; user->range = userrange->range; /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/ if (user->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, user->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (userrange->range != NULL) { rc = cil_resolve_levelrange(current, userrange->range, extra_args); if (rc != SEPOL_OK) { goto exit; } user->range = userrange->range; } return SEPOL_OK; exit: return rc; } int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args) { struct cil_userprefix *userprefix = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = user_datum->nodes->head->data; if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } userprefix->user = (struct cil_user*)user_datum; exit: return rc; } int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) { struct cil_selinuxuser *selinuxuser = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *lvlrange_datum = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = user_datum->nodes->head->data; if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } selinuxuser->user = (struct cil_user*)user_datum; if (selinuxuser->range_str != NULL) { rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } selinuxuser->range = (struct cil_levelrange*)lvlrange_datum; /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/ if (selinuxuser->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (selinuxuser->range != NULL) { rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: return rc; } int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args) { struct cil_roletype *roletype = current->data; struct cil_symtab_datum *role_datum = NULL; struct cil_symtab_datum *type_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, roletype->role_str, CIL_SYM_ROLES, extra_args, &role_datum); if (rc != SEPOL_OK) { goto exit; } roletype->role = (struct cil_role*)role_datum; rc = cil_resolve_name(current, roletype->type_str, CIL_SYM_TYPES, extra_args, &type_datum); if (rc != SEPOL_OK) { goto exit; } roletype->type = (struct cil_type*)type_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args) { struct cil_roletransition *roletrans = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; struct cil_symtab_datum *obj_datum = NULL; struct cil_symtab_datum *result_datum = NULL; struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, roletrans->src_str, CIL_SYM_ROLES, extra_args, &src_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->src = (struct cil_role*)src_datum; rc = cil_resolve_name(current, roletrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->tgt = tgt_datum; rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->obj = (struct cil_class*)obj_datum; rc = cil_resolve_name(current, roletrans->result_str, CIL_SYM_ROLES, extra_args, &result_datum); if (rc != SEPOL_OK) { goto exit; } node = result_datum->nodes->head->data; if (node->flavor != CIL_ROLE) { rc = SEPOL_ERR; printf("%i\n", node->flavor); cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node)); goto exit; } roletrans->result = (struct cil_role*)result_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args) { struct cil_roleallow *roleallow = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, roleallow->src_str, CIL_SYM_ROLES, extra_args, &src_datum); if (rc != SEPOL_OK) { goto exit; } roleallow->src = (struct cil_role*)src_datum; rc = cil_resolve_name(current, roleallow->tgt_str, CIL_SYM_ROLES, extra_args, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } roleallow->tgt = (struct cil_role*)tgt_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_roleattributeset *attrroles = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_roleattribute *attr = NULL; rc = cil_resolve_name(current, attrroles->attr_str, CIL_SYM_ROLES, extra_args, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = attr_datum->nodes->head->data; if (attr_node->flavor != CIL_ROLEATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute role not an attribute\n"); goto exit; } attr = (struct cil_roleattribute*)attr_datum; rc = cil_resolve_expr(CIL_ROLEATTRIBUTESET, attrroles->str_expr, &attrroles->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr); if (rc != SEPOL_OK) { goto exit; } if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE); } cil_list_append(attr->expr_list, CIL_LIST, attrroles->datum_expr); return SEPOL_OK; exit: return rc; } struct cil_ordered_list { int merged; struct cil_list *list; struct cil_tree_node *node; }; void __cil_ordered_list_init(struct cil_ordered_list **ordered) { *ordered = cil_malloc(sizeof(**ordered)); (*ordered)->merged = CIL_FALSE; (*ordered)->list = NULL; (*ordered)->node = NULL; } void __cil_ordered_list_destroy(struct cil_ordered_list **ordered) { cil_list_destroy(&(*ordered)->list, CIL_FALSE); (*ordered)->node = NULL; free(*ordered); *ordered = NULL; } void __cil_ordered_lists_destroy(struct cil_list **ordered_lists) { struct cil_list_item *item = NULL; if (ordered_lists == NULL || *ordered_lists == NULL) { return; } item = (*ordered_lists)->head; while (item != NULL) { struct cil_list_item *next = item->next; struct cil_ordered_list *ordered = item->data; __cil_ordered_list_destroy(&ordered); free(item); item = next; } free(*ordered_lists); *ordered_lists = NULL; } void __cil_ordered_lists_reset(struct cil_list **ordered_lists) { __cil_ordered_lists_destroy(ordered_lists); cil_list_init(ordered_lists, CIL_LIST_ITEM); } struct cil_list_item *__cil_ordered_item_insert(struct cil_list *old, struct cil_list_item *curr, struct cil_list_item *item) { if (item->flavor == CIL_SID) { struct cil_sid *sid = item->data; if (sid->ordered == CIL_TRUE) { cil_log(CIL_ERR, "SID %s has already been merged into the ordered list\n", sid->datum.name); return NULL; } sid->ordered = CIL_TRUE; } else if (item->flavor == CIL_CLASS) { struct cil_class *class = item->data; if (class->ordered == CIL_TRUE) { cil_log(CIL_ERR, "Class %s has already been merged into the ordered list\n", class->datum.name); return NULL; } class->ordered = CIL_TRUE; } else if (item->flavor == CIL_CAT) { struct cil_cat *cat = item->data; if (cat->ordered == CIL_TRUE) { cil_log(CIL_ERR, "Category %s has already been merged into the ordered list\n", cat->datum.name); return NULL; } cat->ordered = CIL_TRUE; } else if (item->flavor == CIL_SENS) { struct cil_sens *sens = item->data; if (sens->ordered == CIL_TRUE) { cil_log(CIL_ERR, "Sensitivity %s has already been merged into the ordered list\n", sens->datum.name); return NULL; } sens->ordered = CIL_TRUE; } return cil_list_insert(old, curr, item->flavor, item->data); } int __cil_ordered_list_insert(struct cil_list *old, struct cil_list_item *ocurr, struct cil_list_item *nstart, struct cil_list_item *nstop) { struct cil_list_item *ncurr = NULL; for (ncurr = nstart; ncurr != nstop; ncurr = ncurr->next) { ocurr = __cil_ordered_item_insert(old, ocurr, ncurr); if (ocurr == NULL) { return SEPOL_ERR; } } return SEPOL_OK; } struct cil_list_item *__cil_ordered_find_match(struct cil_list_item *t, struct cil_list_item *i) { while (i) { if (i->data == t->data) { return i; } i = i->next; } return NULL; } int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new) { struct cil_list_item *omatch = NULL; struct cil_list_item *ofirst = old->head; struct cil_list_item *ocurr = NULL; struct cil_list_item *oprev = NULL; struct cil_list_item *nmatch = NULL; struct cil_list_item *nfirst = new->head; struct cil_list_item *ncurr = NULL; int rc = SEPOL_ERR; if (nfirst == NULL) { return SEPOL_OK; } if (ofirst == NULL) { /* First list added */ rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL); return rc; } /* Find a match between the new list and the old one */ for (nmatch = nfirst; nmatch; nmatch = nmatch->next) { omatch = __cil_ordered_find_match(nmatch, ofirst); if (omatch) { break; } } if (!nmatch) { /* List cannot be merged yet */ return SEPOL_ERR; } if (nmatch != nfirst && omatch != ofirst) { /* Potential ordering conflict--try again later */ return SEPOL_ERR; } if (nmatch != nfirst) { /* Prepend the beginning of the new list up to the first match to the old list */ rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch); if (rc != SEPOL_OK) { return rc; } } /* In the overlapping protion, add items from the new list not in the old list */ ncurr = nmatch->next; ocurr = omatch->next; oprev = omatch; while (ncurr && ocurr) { if (ncurr->data == ocurr->data) { oprev = ocurr; ocurr = ocurr->next; ncurr = ncurr->next; } else { /* Handle gap in old: old = (A C) new = (A B C) */ nmatch = __cil_ordered_find_match(ocurr, ncurr->next); if (nmatch) { rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch); if (rc != SEPOL_OK) { return rc; } oprev = ocurr; ocurr = ocurr->next; ncurr = nmatch->next; continue; } /* Handle gap in new: old = (A B C) new = (A C) */ omatch = __cil_ordered_find_match(ncurr, ocurr->next); if (omatch) { /* Nothing to insert, just skip */ oprev = omatch; ocurr = omatch->next; ncurr = ncurr->next; continue; } else { return SEPOL_ERR; } } } if (ncurr) { /* Add the rest of the items from the new list */ rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL); if (rc != SEPOL_OK) { return rc; } } return SEPOL_OK; } static int insert_unordered(struct cil_list *merged, struct cil_list *unordered) { struct cil_list_item *curr = NULL; struct cil_ordered_list *unordered_list = NULL; struct cil_list_item *item = NULL; struct cil_list_item *ret = NULL; int rc = SEPOL_ERR; cil_list_for_each(curr, unordered) { unordered_list = curr->data; cil_list_for_each(item, unordered_list->list) { if (cil_list_contains(merged, item->data)) { /* item was declared in an ordered statement, which supercedes * all unordered statements */ if (item->flavor == CIL_CLASS) { cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name); } continue; } ret = __cil_ordered_item_insert(merged, merged->tail, item); if (ret == NULL) { rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: return rc; } struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists) { struct cil_list *composite = NULL; struct cil_list_item *curr = NULL; int changed = CIL_TRUE; int waiting = 1; int rc = SEPOL_ERR; cil_list_init(&composite, CIL_LIST_ITEM); while (waiting && changed == CIL_TRUE) { changed = CIL_FALSE; waiting = 0; cil_list_for_each(curr, *ordered_lists) { struct cil_ordered_list *ordered_list = curr->data; if (ordered_list->merged == CIL_FALSE) { rc = __cil_ordered_lists_merge(composite, ordered_list->list); if (rc != SEPOL_OK) { /* Can't merge yet */ waiting++; } else { ordered_list->merged = CIL_TRUE; changed = CIL_TRUE; } } } if (waiting > 0 && changed == CIL_FALSE) { cil_list_for_each(curr, *ordered_lists) { struct cil_ordered_list *ordered_list = curr->data; if (ordered_list->merged == CIL_FALSE) { cil_tree_log(ordered_list->node, CIL_ERR, "Unable to merge ordered list"); } } goto exit; } } if (unordered_lists != NULL) { rc = insert_unordered(composite, *unordered_lists); if (rc != SEPOL_OK) { goto exit; } } __cil_ordered_lists_destroy(ordered_lists); __cil_ordered_lists_destroy(unordered_lists); return composite; exit: __cil_ordered_lists_destroy(ordered_lists); __cil_ordered_lists_destroy(unordered_lists); cil_list_destroy(&composite, CIL_FALSE); return NULL; } int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_list *classorder_list = args->classorder_lists; struct cil_list *unordered_classorder_list = args->unordered_classorder_lists; struct cil_classorder *classorder = current->data; struct cil_list *new = NULL; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; struct cil_ordered_list *class_list = NULL; int rc = SEPOL_ERR; int unordered = CIL_FALSE; cil_list_init(&new, CIL_CLASSORDER); cil_list_for_each(curr, classorder->class_list_str) { if (curr->data == CIL_KEY_UNORDERED) { unordered = CIL_TRUE; continue; } rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data); goto exit; } cil_list_append(new, CIL_CLASS, datum); } __cil_ordered_list_init(&class_list); class_list->list = new; class_list->node = current; if (unordered) { cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list); } else { cil_list_append(classorder_list, CIL_CLASSORDER, class_list); } return SEPOL_OK; exit: cil_list_destroy(&new, CIL_FALSE); return rc; } int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_list *sidorder_list = args->sidorder_lists; struct cil_sidorder *sidorder = current->data; struct cil_list *new = NULL; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; struct cil_ordered_list *ordered = NULL; int rc = SEPOL_ERR; cil_list_init(&new, CIL_SIDORDER); cil_list_for_each(curr, sidorder->sid_list_str) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, extra_args, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data); goto exit; } cil_list_append(new, CIL_SID, datum); } __cil_ordered_list_init(&ordered); ordered->list = new; ordered->node = current; cil_list_append(sidorder_list, CIL_SIDORDER, ordered); return SEPOL_OK; exit: cil_list_destroy(&new, CIL_FALSE); return rc; } void cil_set_cat_values(struct cil_list *ordered_cats, struct cil_db *db) { struct cil_list_item *curr; int v = 0; cil_list_for_each(curr, ordered_cats) { struct cil_cat *cat = curr->data; cat->value = v; v++; } db->num_cats = v; } int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_list *catorder_list = args->catorder_lists; struct cil_catorder *catorder = current->data; struct cil_list *new = NULL; struct cil_list_item *curr = NULL; struct cil_symtab_datum *cat_datum; struct cil_cat *cat = NULL; struct cil_ordered_list *ordered = NULL; int rc = SEPOL_ERR; cil_list_init(&new, CIL_CATORDER); cil_list_for_each(curr, catorder->cat_list_str) { struct cil_tree_node *node = NULL; rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, extra_args, &cat_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data); goto exit; } node = cat_datum->nodes->head->data; if (node->flavor != CIL_CAT) { cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name); rc = SEPOL_ERR; goto exit; } cat = (struct cil_cat *)cat_datum; cil_list_append(new, CIL_CAT, cat); } __cil_ordered_list_init(&ordered); ordered->list = new; ordered->node = current; cil_list_append(catorder_list, CIL_CATORDER, ordered); return SEPOL_OK; exit: cil_list_destroy(&new, CIL_FALSE); return rc; } int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_list *sensitivityorder_list = args->sensitivityorder_lists; struct cil_sensorder *sensorder = current->data; struct cil_list *new = NULL; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; struct cil_ordered_list *ordered = NULL; int rc = SEPOL_ERR; cil_list_init(&new, CIL_LIST_ITEM); cil_list_for_each(curr, sensorder->sens_list_str) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data); goto exit; } cil_list_append(new, CIL_SENS, datum); } __cil_ordered_list_init(&ordered); ordered->list = new; ordered->node = current; cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, ordered); return SEPOL_OK; exit: cil_list_destroy(&new, CIL_FALSE); return rc; } int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, void *extra_args) { int rc = SEPOL_ERR; rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args) { int rc = SEPOL_ERR; rc = cil_resolve_cats(current, catset->cats, extra_args); if (rc != SEPOL_OK) { goto exit; } rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr); if (rc != SEPOL_OK) { cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE); goto exit; } exit: return rc; } int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_senscat *senscat = current->data; struct cil_symtab_datum *sens_datum; struct cil_sens *sens = NULL; rc = cil_resolve_name(current, (char*)senscat->sens_str, CIL_SYM_SENS, extra_args, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); goto exit; } rc = cil_resolve_cats(current, senscat->cats, extra_args); if (rc != SEPOL_OK) { goto exit; } sens = (struct cil_sens *)sens_datum; if (sens->cats_list == NULL ) { cil_list_init(&sens->cats_list, CIL_CAT); } cil_list_append(sens->cats_list, CIL_CAT, senscat->cats); return SEPOL_OK; exit: return rc; } int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args) { struct cil_symtab_datum *sens_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); goto exit; } level->sens = (struct cil_sens *)sens_datum; if (level->cats != NULL) { rc = cil_resolve_cats(current, level->cats, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *lvlrange, void *extra_args) { struct cil_symtab_datum *low_datum = NULL; struct cil_symtab_datum *high_datum = NULL; int rc = SEPOL_ERR; if (lvlrange->low_str != NULL) { rc = cil_resolve_name(current, lvlrange->low_str, CIL_SYM_LEVELS, extra_args, &low_datum); if (rc != SEPOL_OK) { goto exit; } lvlrange->low = (struct cil_level*)low_datum; /* This could still be an anonymous level even if low_str is set, if low_str is a param_str */ if (lvlrange->low->datum.name == NULL) { rc = cil_resolve_level(current, lvlrange->low, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->low != NULL) { rc = cil_resolve_level(current, lvlrange->low, extra_args); if (rc != SEPOL_OK) { goto exit; } } if (lvlrange->high_str != NULL) { rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, extra_args, &high_datum); if (rc != SEPOL_OK) { goto exit; } lvlrange->high = (struct cil_level*)high_datum; /* This could still be an anonymous level even if high_str is set, if high_str is a param_str */ if (lvlrange->high->datum.name == NULL) { rc = cil_resolve_level(current, lvlrange->high, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->high != NULL) { rc = cil_resolve_level(current, lvlrange->high, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args) { struct cil_constrain *cons = current->data; int rc = SEPOL_ERR; rc = cil_resolve_classperms_list(current, cons->classperms, extra_args); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args) { struct cil_validatetrans *validtrans = current->data; struct cil_args_resolve *args = extra_args; struct cil_symtab_datum *class_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, args, &class_datum); if (rc != SEPOL_OK) { goto exit; } validtrans->class = (struct cil_class*)class_datum; rc = cil_resolve_expr(CIL_VALIDATETRANS, validtrans->str_expr, &validtrans->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args) { struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; struct cil_symtab_datum *type_datum = NULL; struct cil_tree_node *node = NULL; struct cil_symtab_datum *lvlrange_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum); if (rc != SEPOL_OK) { goto exit; } node = user_datum->nodes->head->data; if (node->flavor != CIL_USER) { cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } context->user = (struct cil_user*)user_datum; rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum); if (rc != SEPOL_OK) { goto exit; } node = role_datum->nodes->head->data; if (node->flavor != CIL_ROLE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn); goto exit; } context->role = (struct cil_role*)role_datum; rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum); if (rc != SEPOL_OK) { goto exit; } node = type_datum->nodes->head->data; if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Type not a type or type alias\n"); goto exit; } context->type = type_datum; if (context->range_str != NULL) { rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } context->range = (struct cil_levelrange*)lvlrange_datum; /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/ if (context->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, context->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } } else if (context->range != NULL) { rc = cil_resolve_levelrange(current, context->range, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args) { struct cil_filecon *filecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (filecon->context_str != NULL) { rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { return rc; } filecon->context = (struct cil_context*)context_datum; } else if (filecon->context != NULL) { rc = cil_resolve_context(current, filecon->context, extra_args); if (rc != SEPOL_OK) { return rc; } } return SEPOL_OK; } int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args) { struct cil_ibpkeycon *ibpkeycon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (ibpkeycon->context_str) { rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) goto exit; ibpkeycon->context = (struct cil_context *)context_datum; } else { rc = cil_resolve_context(current, ibpkeycon->context, extra_args); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args) { struct cil_portcon *portcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (portcon->context_str != NULL) { rc = cil_resolve_name(current, portcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } portcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, portcon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args) { struct cil_genfscon *genfscon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (genfscon->context_str != NULL) { rc = cil_resolve_name(current, genfscon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } genfscon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, genfscon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args) { struct cil_nodecon *nodecon = current->data; struct cil_symtab_datum *addr_datum = NULL; struct cil_symtab_datum *mask_datum = NULL; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (nodecon->addr_str != NULL) { rc = cil_resolve_name(current, nodecon->addr_str, CIL_SYM_IPADDRS, extra_args, &addr_datum); if (rc != SEPOL_OK) { goto exit; } nodecon->addr = (struct cil_ipaddr*)addr_datum; } if (nodecon->mask_str != NULL) { rc = cil_resolve_name(current, nodecon->mask_str, CIL_SYM_IPADDRS, extra_args, &mask_datum); if (rc != SEPOL_OK) { goto exit; } nodecon->mask = (struct cil_ipaddr*)mask_datum; } if (nodecon->context_str != NULL) { rc = cil_resolve_name(current, nodecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } nodecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, nodecon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } if (nodecon->addr->family != nodecon->mask->family) { cil_log(CIL_ERR, "Nodecon ip address not in the same family\n"); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args) { struct cil_netifcon *netifcon = current->data; struct cil_symtab_datum *ifcon_datum = NULL; struct cil_symtab_datum *packcon_datum = NULL; int rc = SEPOL_ERR; if (netifcon->if_context_str != NULL) { rc = cil_resolve_name(current, netifcon->if_context_str, CIL_SYM_CONTEXTS, extra_args, &ifcon_datum); if (rc != SEPOL_OK) { goto exit; } netifcon->if_context = (struct cil_context*)ifcon_datum; } else { rc = cil_resolve_context(current, netifcon->if_context, extra_args); if (rc != SEPOL_OK) { goto exit; } } if (netifcon->packet_context_str != NULL) { rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, extra_args, &packcon_datum); if (rc != SEPOL_OK) { goto exit; } netifcon->packet_context = (struct cil_context*)packcon_datum; } else { rc = cil_resolve_context(current, netifcon->packet_context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args) { struct cil_ibendportcon *ibendportcon = current->data; struct cil_symtab_datum *con_datum = NULL; int rc = SEPOL_ERR; if (ibendportcon->context_str) { rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &con_datum); if (rc != SEPOL_OK) goto exit; ibendportcon->context = (struct cil_context *)con_datum; } else { rc = cil_resolve_context(current, ibendportcon->context, extra_args); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args) { struct cil_pirqcon *pirqcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (pirqcon->context_str != NULL) { rc = cil_resolve_name(current, pirqcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } pirqcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, pirqcon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args) { struct cil_iomemcon *iomemcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (iomemcon->context_str != NULL) { rc = cil_resolve_name(current, iomemcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } iomemcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, iomemcon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args) { struct cil_ioportcon *ioportcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (ioportcon->context_str != NULL) { rc = cil_resolve_name(current, ioportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } ioportcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, ioportcon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args) { struct cil_pcidevicecon *pcidevicecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (pcidevicecon->context_str != NULL) { rc = cil_resolve_name(current, pcidevicecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } pcidevicecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, pcidevicecon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_devicetreecon(struct cil_tree_node *current, void *extra_args) { struct cil_devicetreecon *devicetreecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (devicetreecon->context_str != NULL) { rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } devicetreecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, devicetreecon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args) { struct cil_fsuse *fsuse = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (fsuse->context_str != NULL) { rc = cil_resolve_name(current, fsuse->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } fsuse->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, fsuse->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args) { struct cil_sidcontext *sidcon = current->data; struct cil_symtab_datum *sid_datum = NULL; struct cil_symtab_datum *context_datum = NULL; struct cil_sid *sid = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, sidcon->sid_str, CIL_SYM_SIDS, extra_args, &sid_datum); if (rc != SEPOL_OK) { goto exit; } sid = (struct cil_sid*)sid_datum; if (sidcon->context_str != NULL) { rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); if (rc != SEPOL_OK) { goto exit; } sidcon->context = (struct cil_context*)context_datum; } else if (sidcon->context != NULL) { rc = cil_resolve_context(current, sidcon->context, extra_args); if (rc != SEPOL_OK) { goto exit; } } if (sid->context != NULL) { cil_log(CIL_ERR, "sid's cannot be associated with more than one context\n"); rc = SEPOL_ERR; goto exit; } sid->context = sidcon->context; return SEPOL_OK; exit: return rc; } int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) { struct cil_blockinherit *inherit = current->data; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); if (rc != SEPOL_OK) { goto exit; } node = block_datum->nodes->head->data; if (node->flavor != CIL_BLOCK) { cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } inherit->block = (struct cil_block *)block_datum; if (inherit->block->bi_nodes == NULL) { cil_list_init(&inherit->block->bi_nodes, CIL_NODE); } cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); return SEPOL_OK; exit: return rc; } void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node) { struct cil_list *trace = NULL; struct cil_list_item *item = NULL; struct cil_tree_node *curr = NULL; cil_list_init(&trace, CIL_NODE); for (curr = bi_node; curr != terminating_node; curr = curr->parent) { if (curr->flavor == CIL_BLOCK) { cil_list_prepend(trace, CIL_NODE, curr); } else { if (curr != bi_node) { cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block)); } cil_list_prepend(trace, CIL_NODE, curr); } } cil_list_prepend(trace, CIL_NODE, terminating_node); cil_list_for_each(item, trace) { curr = item->data; if (curr->flavor == CIL_BLOCK) { cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name); } else { cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str); } } cil_list_destroy(&trace, CIL_FALSE); } int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node) { struct cil_tree_node *curr = NULL; struct cil_blockinherit *bi = NULL; struct cil_block *block = NULL; int rc = SEPOL_ERR; bi = bi_node->data; for (curr = bi_node->parent; curr != NULL; curr = curr->parent) { if (curr->flavor != CIL_BLOCK) { continue; } block = curr->data; if (block != bi->block) { continue; } cil_log(CIL_ERR, "Recursive blockinherit found:\n"); cil_print_recursive_blockinherit(bi_node, curr); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: return rc; } int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) { struct cil_block *block = current->data; struct cil_args_resolve *args = extra_args; struct cil_db *db = NULL; struct cil_list_item *item = NULL; int rc = SEPOL_ERR; // This block is not inherited if (block->bi_nodes == NULL) { rc = SEPOL_OK; goto exit; } db = args->db; // Make sure this is the original block and not a merged block from a blockinherit if (current != block->datum.nodes->head->data) { rc = SEPOL_OK; goto exit; } cil_list_for_each(item, block->bi_nodes) { rc = cil_check_recursive_blockinherit(item->data); if (rc != SEPOL_OK) { goto exit; } rc = cil_copy_ast(db, current, item->data); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n"); goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args) { struct cil_blockabstract *abstract = current->data; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *block_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); if (rc != SEPOL_OK) { goto exit; } block_node = block_datum->nodes->head->data; if (block_node->flavor != CIL_BLOCK) { cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc); goto exit; } ((struct cil_block*)block_datum)->is_abstract = CIL_TRUE; return SEPOL_OK; exit: return rc; } int cil_resolve_in(struct cil_tree_node *current, void *extra_args) { struct cil_in *in = current->data; struct cil_args_resolve *args = extra_args; struct cil_db *db = NULL; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *block_node = NULL; int rc = SEPOL_ERR; if (args != NULL) { db = args->db; } rc = cil_resolve_name(current, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); if (rc != SEPOL_OK) { goto exit; } block_node = block_datum->nodes->head->data; rc = cil_copy_ast(db, current, block_node); if (rc != SEPOL_OK) { printf("Failed to copy in, rc: %d\n", rc); goto exit; } cil_tree_children_destroy(current); current->cl_head = NULL; current->cl_tail = NULL; return SEPOL_OK; exit: return rc; } int cil_resolve_in_list(void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_list *ins = args->in_list; struct cil_list_item *curr = NULL; struct cil_tree_node *node = NULL; struct cil_tree_node *last_failed_node = NULL; struct cil_in *in = NULL; struct cil_symtab_datum *block_datum = NULL; int resolved = 0; int unresolved = 0; int rc = SEPOL_ERR; do { resolved = 0; unresolved = 0; cil_list_for_each(curr, ins) { if (curr->flavor != CIL_NODE) { continue; } node = curr->data; in = node->data; rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); if (rc != SEPOL_OK) { unresolved++; last_failed_node = node; } else { rc = cil_resolve_in(node, extra_args); if (rc != SEPOL_OK) { goto exit; } resolved++; curr->data = NULL; curr->flavor = CIL_NONE; } } if (unresolved > 0 && resolved == 0) { cil_tree_log(last_failed_node, CIL_ERR, "Failed to resolve in-statement"); rc = SEPOL_ERR; goto exit; } } while (unresolved > 0); rc = SEPOL_OK; exit: return rc; } int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor) { int rc = SEPOL_ERR; struct cil_bounds *bounds = current->data; enum cil_sym_index index; struct cil_symtab_datum *parent_datum = NULL; struct cil_symtab_datum *child_datum = NULL; rc = cil_flavor_to_symtab_index(flavor, &index); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_name(current, bounds->parent_str, index, extra_args, &parent_datum); if (rc != SEPOL_OK) { goto exit; } if (NODE(parent_datum)->flavor == attr_flavor) { cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum); if (rc != SEPOL_OK) { goto exit; } if (NODE(child_datum)->flavor == attr_flavor) { cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str); rc = SEPOL_ERR; goto exit; } switch (flavor) { case CIL_USER: { struct cil_user *user = (struct cil_user *)child_datum; if (user->bounds != NULL) { cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } user->bounds = (struct cil_user *)parent_datum; break; } case CIL_ROLE: { struct cil_role *role = (struct cil_role *)child_datum; if (role->bounds != NULL) { cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } role->bounds = (struct cil_role *)parent_datum; break; } case CIL_TYPE: { struct cil_type *type = (struct cil_type *)child_datum; if (type->bounds != NULL) { cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } type->bounds = (struct cil_type *)parent_datum; break; } default: break; } return SEPOL_OK; exit: cil_tree_log(current, CIL_ERR, "Bad bounds statement"); return rc; } int cil_resolve_default(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_default *def = current->data; struct cil_list_item *curr; struct cil_symtab_datum *datum; cil_list_init(&def->class_datums, def->flavor); cil_list_for_each(curr, def->class_strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; } cil_list_append(def->class_datums, CIL_CLASS, datum); } return SEPOL_OK; exit: return rc; } int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_defaultrange *def = current->data; struct cil_list_item *curr; struct cil_symtab_datum *datum; cil_list_init(&def->class_datums, CIL_DEFAULTRANGE); cil_list_for_each(curr, def->class_strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; } cil_list_append(def->class_datums, CIL_CLASS, datum); } return SEPOL_OK; exit: return rc; } void cil_print_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *terminating_node) { struct cil_list *trace = NULL; struct cil_list_item * item = NULL; struct cil_tree_node *curr = NULL; cil_list_init(&trace, CIL_NODE); for (curr = call_node; curr != terminating_node; curr = curr->parent) { if (curr->flavor == CIL_CALL) { if (curr != call_node) { cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)curr->data)->macro)); } cil_list_prepend(trace, CIL_NODE, curr); } } if (terminating_node->flavor == CIL_MACRO) { cil_list_prepend(trace, CIL_NODE, terminating_node); } else { cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)terminating_node->data)->macro)); } cil_list_for_each(item, trace) { curr = item->data; if (curr->flavor == CIL_MACRO) { cil_tree_log(curr, CIL_ERR, "macro %s", DATUM(curr->data)->name); } else { cil_tree_log(curr, CIL_ERR, "call %s", ((struct cil_call *)curr->data)->macro_str); } } cil_list_destroy(&trace, CIL_FALSE); } int cil_check_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *macro_node) { struct cil_tree_node *curr = NULL; struct cil_call * call = NULL; int rc = SEPOL_ERR; for (curr = call_node; curr != NULL; curr = curr->parent) { if (curr->flavor == CIL_CALL) { if (curr == call_node) { continue; } call = curr->data; if (call->macro != macro_node->data) { continue; } } else if (curr->flavor == CIL_MACRO) { if (curr != macro_node) { rc = SEPOL_OK; goto exit; } } else { continue; } cil_log(CIL_ERR, "Recursive macro call found:\n"); cil_print_recursive_call(call_node, curr); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: return rc; } int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) { struct cil_call *new_call = current->data; struct cil_args_resolve *args = extra_args; struct cil_db *db = NULL; struct cil_tree_node *macro_node = NULL; struct cil_symtab_datum *macro_datum = NULL; int rc = SEPOL_ERR; if (args != NULL) { db = args->db; } rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum); if (rc != SEPOL_OK) { goto exit; } macro_node = macro_datum->nodes->head->data; if (macro_node->flavor != CIL_MACRO) { printf("Failed to resolve %s to a macro\n", new_call->macro_str); rc = SEPOL_ERR; goto exit; } new_call->macro = (struct cil_macro*)macro_datum; if (new_call->macro->params != NULL ) { struct cil_list_item *item; struct cil_args *new_arg = NULL; struct cil_tree_node *pc = NULL; if (new_call->args_tree == NULL) { cil_tree_log(current, CIL_ERR, "Missing arguments"); rc = SEPOL_ERR; goto exit; } pc = new_call->args_tree->root->cl_head; cil_list_init(&new_call->args, CIL_LIST_ITEM); cil_list_for_each(item, new_call->macro->params) { enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor; if (pc == NULL) { cil_tree_log(current, CIL_ERR, "Missing arguments"); rc = SEPOL_ERR; goto exit; } if (item->flavor != CIL_PARAM) { rc = SEPOL_ERR; goto exit; } cil_args_init(&new_arg); switch (flavor) { case CIL_NAME: { struct cil_name *name; name = __cil_insert_name(args->db, pc->data, current); if (name != NULL) { new_arg->arg = (struct cil_symtab_datum *)name; } else { new_arg->arg_str = pc->data; } } break; case CIL_TYPE: new_arg->arg_str = pc->data; break; case CIL_ROLE: new_arg->arg_str = pc->data; break; case CIL_USER: new_arg->arg_str = pc->data; break; case CIL_SENS: new_arg->arg_str = pc->data; break; case CIL_CAT: new_arg->arg_str = pc->data; break; case CIL_BOOL: new_arg->arg_str = pc->data; break; case CIL_CATSET: { if (pc->cl_head != NULL) { struct cil_catset *catset = NULL; struct cil_tree_node *cat_node = NULL; cil_catset_init(&catset); rc = cil_fill_cats(pc, &catset->cats); if (rc != SEPOL_OK) { cil_destroy_catset(catset); cil_destroy_args(new_arg); goto exit; } cil_tree_node_init(&cat_node); cat_node->flavor = CIL_CATSET; cat_node->data = catset; cil_list_append(((struct cil_symtab_datum*)catset)->nodes, CIL_LIST_ITEM, cat_node); new_arg->arg = (struct cil_symtab_datum*)catset; } else { new_arg->arg_str = pc->data; } break; } case CIL_LEVEL: { if (pc->cl_head != NULL) { struct cil_level *level = NULL; struct cil_tree_node *lvl_node = NULL; cil_level_init(&level); rc = cil_fill_level(pc->cl_head, level); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc); cil_destroy_level(level); cil_destroy_args(new_arg); goto exit; } cil_tree_node_init(&lvl_node); lvl_node->flavor = CIL_LEVEL; lvl_node->data = level; cil_list_append(((struct cil_symtab_datum*)level)->nodes, CIL_LIST_ITEM, lvl_node); new_arg->arg = (struct cil_symtab_datum*)level; } else { new_arg->arg_str = pc->data; } break; } case CIL_LEVELRANGE: { if (pc->cl_head != NULL) { struct cil_levelrange *range = NULL; struct cil_tree_node *range_node = NULL; cil_levelrange_init(&range); rc = cil_fill_levelrange(pc->cl_head, range); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc); cil_destroy_levelrange(range); cil_destroy_args(new_arg); goto exit; } cil_tree_node_init(&range_node); range_node->flavor = CIL_LEVELRANGE; range_node->data = range; cil_list_append(((struct cil_symtab_datum*)range)->nodes, CIL_LIST_ITEM, range_node); new_arg->arg = (struct cil_symtab_datum*)range; } else { new_arg->arg_str = pc->data; } break; } case CIL_IPADDR: { if (pc->cl_head != NULL) { struct cil_ipaddr *ipaddr = NULL; struct cil_tree_node *addr_node = NULL; cil_ipaddr_init(&ipaddr); rc = cil_fill_ipaddr(pc->cl_head, ipaddr); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc); cil_destroy_ipaddr(ipaddr); cil_destroy_args(new_arg); goto exit; } cil_tree_node_init(&addr_node); addr_node->flavor = CIL_IPADDR; addr_node->data = ipaddr; cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes, CIL_LIST_ITEM, addr_node); new_arg->arg = (struct cil_symtab_datum*)ipaddr; } else { new_arg->arg_str = pc->data; } break; } case CIL_CLASS: new_arg->arg_str = pc->data; break; case CIL_MAP_CLASS: new_arg->arg_str = pc->data; break; case CIL_CLASSPERMISSION: { if (pc->cl_head != NULL) { struct cil_classpermission *cp = NULL; struct cil_tree_node *cp_node = NULL; cil_classpermission_init(&cp); rc = cil_fill_classperms_list(pc, &cp->classperms); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous classpermission\n"); cil_destroy_classpermission(cp); cil_destroy_args(new_arg); goto exit; } cil_tree_node_init(&cp_node); cp_node->flavor = CIL_CLASSPERMISSION; cp_node->data = cp; cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node); new_arg->arg = (struct cil_symtab_datum*)cp; } else { new_arg->arg_str = pc->data; } break; } default: cil_log(CIL_ERR, "Unexpected flavor: %d\n", (((struct cil_param*)item->data)->flavor)); cil_destroy_args(new_arg); rc = SEPOL_ERR; goto exit; } new_arg->param_str = ((struct cil_param*)item->data)->str; new_arg->flavor = flavor; cil_list_append(new_call->args, CIL_ARGS, new_arg); pc = pc->next; } if (pc != NULL) { cil_tree_log(current, CIL_ERR, "Unexpected arguments"); rc = SEPOL_ERR; goto exit; } } else if (new_call->args_tree != NULL) { cil_tree_log(current, CIL_ERR, "Unexpected arguments"); rc = SEPOL_ERR; goto exit; } if (new_call->copied == 0) { new_call->copied = 1; rc = cil_check_recursive_call(current, macro_node); if (rc != SEPOL_OK) { goto exit; } rc = cil_copy_ast(db, macro_node, current); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc); goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_call2(struct cil_tree_node *current, void *extra_args) { struct cil_call *new_call = current->data; int rc = SEPOL_ERR; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; struct cil_list_item *item; if (new_call->args == NULL) { rc = SEPOL_OK; goto exit; } cil_list_for_each(item, new_call->args) { struct cil_args *arg = item->data; if (arg->arg == NULL && arg->arg_str == NULL) { cil_log(CIL_ERR, "Arguments not created correctly\n"); rc = SEPOL_ERR; goto exit; } switch (arg->flavor) { case CIL_NAME: if (arg->arg != NULL) { continue; /* No need to resolve */ } else { sym_index = CIL_SYM_NAMES; } break; case CIL_LEVEL: if (arg->arg_str == NULL && arg->arg != NULL) { continue; // anonymous, no need to resolve } else { sym_index = CIL_SYM_LEVELS; } break; case CIL_LEVELRANGE: if (arg->arg_str == NULL && arg->arg != NULL) { continue; // anonymous, no need to resolve } else { sym_index = CIL_SYM_LEVELRANGES; } break; case CIL_CATSET: if (arg->arg_str == NULL && arg->arg != NULL) { continue; // anonymous, no need to resolve } else { sym_index = CIL_SYM_CATS; } break; case CIL_IPADDR: if (arg->arg_str == NULL && arg->arg != NULL) { continue; // anonymous, no need to resolve } else { sym_index = CIL_SYM_IPADDRS; } break; case CIL_CLASSPERMISSION: if (arg->arg_str == NULL && arg->arg != NULL) { continue; } else { sym_index = CIL_SYM_CLASSPERMSETS; } break; case CIL_TYPE: if (arg->arg_str == NULL && arg->arg != NULL) { continue; // anonymous, no need to resolve } else { sym_index = CIL_SYM_TYPES; } break; case CIL_ROLE: sym_index = CIL_SYM_ROLES; break; case CIL_USER: sym_index = CIL_SYM_USERS; break; case CIL_SENS: sym_index = CIL_SYM_SENS; break; case CIL_CAT: sym_index = CIL_SYM_CATS; break; case CIL_CLASS: case CIL_MAP_CLASS: sym_index = CIL_SYM_CLASSES; break; case CIL_BOOL: sym_index = CIL_SYM_BOOLS; break; default: rc = SEPOL_ERR; goto exit; } if (sym_index != CIL_SYM_UNKNOWN) { rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg)); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { struct cil_list_item *item; enum cil_sym_index param_index = CIL_SYM_UNKNOWN; int rc = SEPOL_ERR; if (call == NULL || name == NULL) { goto exit; } if (call->args == NULL) { goto exit; } cil_list_for_each(item, call->args) { struct cil_args * arg = item->data; rc = cil_flavor_to_symtab_index(arg->flavor, ¶m_index); if (param_index == sym_index) { if (name == arg->param_str) { *datum = arg->arg; rc = SEPOL_OK; goto exit; } } } return SEPOL_ERR; exit: return rc; } int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args) { int rc = SEPOL_ERR; struct cil_list_item *curr; struct cil_symtab_datum *res_datum = NULL; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; switch (str_expr->flavor) { case CIL_BOOL: sym_index = CIL_SYM_BOOLS; break; case CIL_TUNABLE: sym_index = CIL_SYM_TUNABLES; break; case CIL_TYPE: sym_index = CIL_SYM_TYPES; break; case CIL_ROLE: sym_index = CIL_SYM_ROLES; break; case CIL_USER: sym_index = CIL_SYM_USERS; break; case CIL_CAT: sym_index = CIL_SYM_CATS; break; default: break; } cil_list_init(datum_expr, str_expr->flavor); cil_list_for_each(curr, str_expr) { switch (curr->flavor) { case CIL_STRING: rc = cil_resolve_name(parent, curr->data, sym_index, extra_args, &res_datum); if (rc != SEPOL_OK) { goto exit; } if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) { cil_type_used(res_datum, CIL_ATTR_CONSTRAINT); } cil_list_append(*datum_expr, CIL_DATUM, res_datum); break; case CIL_LIST: { struct cil_list *datum_sub_expr; rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args); if (rc != SEPOL_OK) { cil_list_destroy(&datum_sub_expr, CIL_TRUE); goto exit; } cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr); break; } default: cil_list_append(*datum_expr, curr->flavor, curr->data); break; } } return SEPOL_OK; exit: return rc; } int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_booleanif *bif = (struct cil_booleanif*)current->data; rc = cil_resolve_expr(CIL_BOOLEANIF, bif->str_expr, &bif->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_evaluate_tunable_expr(struct cil_list_item *curr); static int __cil_evaluate_tunable_expr_helper(struct cil_list_item *curr) { if (curr == NULL) { return CIL_FALSE; } else if (curr->flavor == CIL_DATUM) { struct cil_tunable *tun = curr->data; return tun->value; } else if (curr->flavor == CIL_LIST) { struct cil_list *l = curr->data; return __cil_evaluate_tunable_expr(l->head); } else { return CIL_FALSE; } } static int __cil_evaluate_tunable_expr(struct cil_list_item *curr) { /* Assumes expression is well-formed */ if (curr == NULL) { return CIL_FALSE; } else if (curr->flavor == CIL_OP) { uint16_t v1, v2; enum cil_flavor op_flavor = (enum cil_flavor)curr->data; v1 = __cil_evaluate_tunable_expr_helper(curr->next); if (op_flavor == CIL_NOT) return !v1; v2 = __cil_evaluate_tunable_expr_helper(curr->next->next); if (op_flavor == CIL_AND) return (v1 && v2); else if (op_flavor == CIL_OR) return (v1 || v2); else if (op_flavor == CIL_XOR) return (v1 ^ v2); else if (op_flavor == CIL_EQ) return (v1 == v2); else if (op_flavor == CIL_NEQ) return (v1 != v2); else return CIL_FALSE; } else { uint16_t v; for (;curr; curr = curr->next) { v = __cil_evaluate_tunable_expr_helper(curr); if (v) return v; } return CIL_FALSE; } } int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args) { struct cil_args_resolve *args = extra_args; struct cil_db *db = NULL; int rc = SEPOL_ERR; struct cil_tunableif *tif = (struct cil_tunableif*)current->data; uint16_t result = CIL_FALSE; struct cil_tree_node *true_node = NULL; struct cil_tree_node *false_node = NULL; struct cil_condblock *cb = NULL; if (args != NULL) { db = args->db; } rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } result = __cil_evaluate_tunable_expr(tif->datum_expr->head); if (current->cl_head != NULL && current->cl_head->flavor == CIL_CONDBLOCK) { cb = current->cl_head->data; if (cb->flavor == CIL_CONDTRUE) { true_node = current->cl_head; } else if (cb->flavor == CIL_CONDFALSE) { false_node = current->cl_head; } } if (current->cl_head != NULL && current->cl_head->next != NULL && current->cl_head->next->flavor == CIL_CONDBLOCK) { cb = current->cl_head->next->data; if (cb->flavor == CIL_CONDTRUE) { true_node = current->cl_head->next; } else if (cb->flavor == CIL_CONDFALSE) { false_node = current->cl_head->next; } } if (result == CIL_TRUE) { if (true_node != NULL) { rc = cil_copy_ast(db, true_node, current->parent); if (rc != SEPOL_OK) { goto exit; } } } else { if (false_node != NULL) { rc = cil_copy_ast(db, false_node, current->parent); if (rc != SEPOL_OK) { goto exit; } } } cil_tree_children_destroy(current); current->cl_head = NULL; current->cl_tail = NULL; return SEPOL_OK; exit: return rc; } int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_userattributeset *attrusers = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_userattribute *attr = NULL; rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, extra_args, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = attr_datum->nodes->head->data; if (attr_node->flavor != CIL_USERATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute user not an attribute\n"); goto exit; } attr = (struct cil_userattribute*)attr_datum; rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, extra_args); if (rc != SEPOL_OK) { goto exit; } rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr); if (rc != SEPOL_OK) { goto exit; } if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE); } cil_list_append(attr->expr_list, CIL_LIST, attrusers->datum_expr); return SEPOL_OK; exit: return rc; } int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) { int rc = SEPOL_OK; struct cil_args_resolve *args = extra_args; enum cil_pass pass = 0; struct cil_list *ins; if (node == NULL || args == NULL) { goto exit; } ins = args->in_list; pass = args->pass; switch (pass) { case CIL_PASS_TIF: if (node->flavor == CIL_TUNABLEIF) { rc = cil_resolve_tunif(node, args); } break; case CIL_PASS_IN: if (node->flavor == CIL_IN) { // due to ordering issues, in statements are just gathered here and // resolved together in cil_resolve_in_list once all are found cil_list_prepend(ins, CIL_NODE, node); } break; case CIL_PASS_BLKIN_LINK: if (node->flavor == CIL_BLOCKINHERIT) { rc = cil_resolve_blockinherit_link(node, args); } break; case CIL_PASS_BLKIN_COPY: if (node->flavor == CIL_BLOCK) { rc = cil_resolve_blockinherit_copy(node, args); } break; case CIL_PASS_BLKABS: if (node->flavor == CIL_BLOCKABSTRACT) { rc = cil_resolve_blockabstract(node, args); } break; case CIL_PASS_MACRO: if (node->flavor == CIL_CALL && args->macro != NULL) { rc = cil_resolve_call1(node, args); } break; case CIL_PASS_CALL1: if (node->flavor == CIL_CALL) { rc = cil_resolve_call1(node, args); } break; case CIL_PASS_CALL2: if (node->flavor == CIL_CALL) { rc = cil_resolve_call2(node, args); } break; case CIL_PASS_ALIAS1: switch (node->flavor) { case CIL_TYPEALIASACTUAL: rc = cil_resolve_aliasactual(node, args, CIL_TYPE, CIL_TYPEALIAS); break; case CIL_SENSALIASACTUAL: rc = cil_resolve_aliasactual(node, args, CIL_SENS, CIL_SENSALIAS); break; case CIL_CATALIASACTUAL: rc = cil_resolve_aliasactual(node, args, CIL_CAT, CIL_CATALIAS); break; default: break; } break; case CIL_PASS_ALIAS2: switch (node->flavor) { case CIL_TYPEALIAS: rc = cil_resolve_alias_to_actual(node, CIL_TYPE); break; case CIL_SENSALIAS: rc = cil_resolve_alias_to_actual(node, CIL_SENS); break; case CIL_CATALIAS: rc = cil_resolve_alias_to_actual(node, CIL_CAT); break; default: break; } break; case CIL_PASS_MISC1: switch (node->flavor) { case CIL_SIDORDER: rc = cil_resolve_sidorder(node, args); break; case CIL_CLASSORDER: rc = cil_resolve_classorder(node, args); break; case CIL_CATORDER: rc = cil_resolve_catorder(node, args); break; case CIL_SENSITIVITYORDER: rc = cil_resolve_sensitivityorder(node, args); break; case CIL_BOOLEANIF: rc = cil_resolve_boolif(node, args); break; default: break; } break; case CIL_PASS_MLS: switch (node->flavor) { case CIL_CATSET: rc = cil_resolve_catset(node, (struct cil_catset*)node->data, args); break; default: break; } break; case CIL_PASS_MISC2: switch (node->flavor) { case CIL_SENSCAT: rc = cil_resolve_senscat(node, args); break; case CIL_CLASSCOMMON: rc = cil_resolve_classcommon(node, args); break; default: break; } break; case CIL_PASS_MISC3: switch (node->flavor) { case CIL_TYPEATTRIBUTESET: rc = cil_resolve_typeattributeset(node, args); break; case CIL_EXPANDTYPEATTRIBUTE: rc = cil_resolve_expandtypeattribute(node, args); break; case CIL_TYPEBOUNDS: rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE); break; case CIL_TYPEPERMISSIVE: rc = cil_resolve_typepermissive(node, args); break; case CIL_NAMETYPETRANSITION: rc = cil_resolve_nametypetransition(node, args); break; case CIL_RANGETRANSITION: rc = cil_resolve_rangetransition(node, args); break; case CIL_CLASSPERMISSIONSET: rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, args); break; case CIL_CLASSMAPPING: rc = cil_resolve_classmapping(node, args); break; case CIL_AVRULE: case CIL_AVRULEX: rc = cil_resolve_avrule(node, args); break; case CIL_PERMISSIONX: rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, args); break; case CIL_TYPE_RULE: rc = cil_resolve_type_rule(node, args); break; case CIL_USERROLE: rc = cil_resolve_userrole(node, args); break; case CIL_USERLEVEL: rc = cil_resolve_userlevel(node, args); break; case CIL_USERRANGE: rc = cil_resolve_userrange(node, args); break; case CIL_USERBOUNDS: rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE); break; case CIL_USERPREFIX: rc = cil_resolve_userprefix(node, args); break; case CIL_SELINUXUSER: case CIL_SELINUXUSERDEFAULT: rc = cil_resolve_selinuxuser(node, args); break; case CIL_ROLEATTRIBUTESET: rc = cil_resolve_roleattributeset(node, args); break; case CIL_ROLETYPE: rc = cil_resolve_roletype(node, args); break; case CIL_ROLETRANSITION: rc = cil_resolve_roletransition(node, args); break; case CIL_ROLEALLOW: rc = cil_resolve_roleallow(node, args); break; case CIL_ROLEBOUNDS: rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE); break; case CIL_LEVEL: rc = cil_resolve_level(node, (struct cil_level*)node->data, args); break; case CIL_LEVELRANGE: rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, args); break; case CIL_CONSTRAIN: rc = cil_resolve_constrain(node, args); break; case CIL_MLSCONSTRAIN: rc = cil_resolve_constrain(node, args); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: rc = cil_resolve_validatetrans(node, args); break; case CIL_CONTEXT: rc = cil_resolve_context(node, (struct cil_context*)node->data, args); break; case CIL_FILECON: rc = cil_resolve_filecon(node, args); break; case CIL_IBPKEYCON: rc = cil_resolve_ibpkeycon(node, args); break; case CIL_PORTCON: rc = cil_resolve_portcon(node, args); break; case CIL_NODECON: rc = cil_resolve_nodecon(node, args); break; case CIL_GENFSCON: rc = cil_resolve_genfscon(node, args); break; case CIL_NETIFCON: rc = cil_resolve_netifcon(node, args); break; case CIL_IBENDPORTCON: rc = cil_resolve_ibendportcon(node, args); break; case CIL_PIRQCON: rc = cil_resolve_pirqcon(node, args); break; case CIL_IOMEMCON: rc = cil_resolve_iomemcon(node, args); break; case CIL_IOPORTCON: rc = cil_resolve_ioportcon(node, args); break; case CIL_PCIDEVICECON: rc = cil_resolve_pcidevicecon(node, args); break; case CIL_DEVICETREECON: rc = cil_resolve_devicetreecon(node, args); break; case CIL_FSUSE: rc = cil_resolve_fsuse(node, args); break; case CIL_SIDCONTEXT: rc = cil_resolve_sidcontext(node, args); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: rc = cil_resolve_default(node, args); break; case CIL_DEFAULTRANGE: rc = cil_resolve_defaultrange(node, args); break; case CIL_USERATTRIBUTESET: rc = cil_resolve_userattributeset(node, args); break; default: break; } break; default: break; } return rc; exit: return rc; } int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; enum cil_pass pass = args->pass; struct cil_tree_node *optstack = args->optstack; struct cil_tree_node *boolif = args->boolif; struct cil_tree_node *blockstack = args->blockstack; struct cil_tree_node *macro = args->macro; if (node == NULL) { goto exit; } if (optstack != NULL) { if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) { /* tuanbles and macros are not allowed in optionals*/ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (blockstack != NULL) { if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) { cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (macro != NULL) { if (node->flavor == CIL_BLOCKINHERIT || node->flavor == CIL_BLOCK || node->flavor == CIL_BLOCKABSTRACT || node->flavor == CIL_MACRO) { cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (boolif != NULL) { if (!(node->flavor == CIL_CONDBLOCK || node->flavor == CIL_AVRULE || node->flavor == CIL_TYPE_RULE || node->flavor == CIL_CALL || node->flavor == CIL_TUNABLEIF || node->flavor == CIL_NAMETYPETRANSITION)) { if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node)); } else { cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node)); } rc = SEPOL_ERR; goto exit; } } if (node->flavor == CIL_MACRO) { if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } } if (node->flavor == CIL_BLOCK && ((((struct cil_block*)node->data)->is_abstract == CIL_TRUE) && (pass > CIL_PASS_BLKABS))) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } rc = __cil_resolve_ast_node(node, extra_args); if (rc == SEPOL_ENOENT) { enum cil_log_level lvl = CIL_ERR; if (optstack != NULL) { lvl = CIL_WARN; struct cil_optional *opt = (struct cil_optional *)optstack->data; struct cil_tree_node *opt_node = opt->datum.nodes->head->data; cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name); /* disable an optional if something failed to resolve */ opt->enabled = CIL_FALSE; rc = SEPOL_OK; } cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); goto exit; } return rc; exit: return rc; } int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; struct cil_tree_node *optstack = NULL; struct cil_tree_node *parent = NULL; struct cil_tree_node *blockstack = NULL; struct cil_tree_node *new = NULL; if (current == NULL || extra_args == NULL) { goto exit; } optstack = args->optstack; parent = current->parent; blockstack = args->blockstack; if (parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) { /* push this node onto a stack */ cil_tree_node_init(&new); new->data = parent->data; new->flavor = parent->flavor; if (parent->flavor == CIL_OPTIONAL) { if (optstack != NULL) { optstack->parent = new; new->cl_head = optstack; } args->optstack = new; } else if (parent->flavor == CIL_BLOCK) { if (blockstack != NULL) { blockstack->parent = new; new->cl_head = blockstack; } args->blockstack = new; } } else if (parent->flavor == CIL_BOOLEANIF) { args->boolif = parent; } else if (parent->flavor == CIL_MACRO) { args->macro = parent; } return SEPOL_OK; exit: return rc; } int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; struct cil_tree_node *parent = NULL; struct cil_tree_node *blockstack = NULL; if (current == NULL || extra_args == NULL) { goto exit; } parent = current->parent; if (parent->flavor == CIL_MACRO) { args->macro = NULL; } else if (parent->flavor == CIL_OPTIONAL) { struct cil_tree_node *optstack; if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { *(args->changed) = CIL_TRUE; cil_tree_children_destroy(parent); } /* pop off the stack */ optstack = args->optstack; args->optstack = optstack->cl_head; if (optstack->cl_head) { optstack->cl_head->parent = NULL; } free(optstack); } else if (parent->flavor == CIL_BOOLEANIF) { args->boolif = NULL; } else if (parent->flavor == CIL_BLOCK) { /* pop off the stack */ blockstack = args->blockstack; args->blockstack = blockstack->cl_head; if (blockstack->cl_head) { blockstack->cl_head->parent = NULL; } free(blockstack); } return SEPOL_OK; exit: return rc; } static void cil_destroy_tree_node_stack(struct cil_tree_node *curr) { struct cil_tree_node *next; while (curr != NULL) { next = curr->cl_head; free(curr); curr = next; } } int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) { int rc = SEPOL_ERR; struct cil_args_resolve extra_args; enum cil_pass pass = CIL_PASS_TIF; uint32_t changed = 0; if (db == NULL || current == NULL) { return rc; } extra_args.db = db; extra_args.pass = pass; extra_args.changed = &changed; extra_args.last_resolved_name = NULL; extra_args.optstack = NULL; extra_args.boolif= NULL; extra_args.macro = NULL; extra_args.sidorder_lists = NULL; extra_args.classorder_lists = NULL; extra_args.unordered_classorder_lists = NULL; extra_args.catorder_lists = NULL; extra_args.sensitivityorder_lists = NULL; extra_args.in_list = NULL; extra_args.blockstack = NULL; cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM); cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM); cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM); cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM); cil_list_init(&extra_args.in_list, CIL_IN); for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) { extra_args.pass = pass; rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Pass %i of resolution failed\n", pass); goto exit; } if (pass == CIL_PASS_IN) { rc = cil_resolve_in_list(&extra_args); if (rc != SEPOL_OK) { goto exit; } cil_list_destroy(&extra_args.in_list, CIL_FALSE); } if (pass == CIL_PASS_MISC1) { db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists, NULL); if (db->sidorder == NULL) { rc = SEPOL_ERR; goto exit; } db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists, &extra_args.unordered_classorder_lists); if (db->classorder == NULL) { rc = SEPOL_ERR; goto exit; } db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists, NULL); if (db->catorder == NULL) { rc = SEPOL_ERR; goto exit; } cil_set_cat_values(db->catorder, db); db->sensitivityorder = __cil_ordered_lists_merge_all(&extra_args.sensitivityorder_lists, NULL); if (db->sensitivityorder == NULL) { rc = SEPOL_ERR; goto exit; } rc = __cil_verify_ordered(current, CIL_SID); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_CLASS); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_CAT); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_SENS); if (rc != SEPOL_OK) { goto exit; } } if (changed && (pass > CIL_PASS_CALL1)) { /* Need to re-resolve because an optional was disabled that contained * one or more declarations. We only need to reset to the call1 pass * because things done in the preceeding passes aren't allowed in * optionals, and thus can't be disabled. * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment * it to CIL_PASS_CALL2 */ cil_log(CIL_INFO, "Resetting declarations\n"); if (pass >= CIL_PASS_MISC1) { __cil_ordered_lists_reset(&extra_args.sidorder_lists); __cil_ordered_lists_reset(&extra_args.classorder_lists); __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists); __cil_ordered_lists_reset(&extra_args.catorder_lists); __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists); cil_list_destroy(&db->sidorder, CIL_FALSE); cil_list_destroy(&db->classorder, CIL_FALSE); cil_list_destroy(&db->catorder, CIL_FALSE); cil_list_destroy(&db->sensitivityorder, CIL_FALSE); } pass = CIL_PASS_CALL1; rc = cil_reset_ast(current); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to reset declarations\n"); goto exit; } } /* reset the arguments */ changed = 0; while (extra_args.optstack != NULL) { cil_destroy_tree_node_stack(extra_args.optstack); extra_args.optstack = NULL; } while (extra_args.blockstack!= NULL) { cil_destroy_tree_node_stack(extra_args.blockstack); extra_args.blockstack = NULL; } } rc = __cil_verify_initsids(db->sidorder); if (rc != SEPOL_OK) { goto exit; } rc = SEPOL_OK; exit: cil_destroy_tree_node_stack(extra_args.optstack); cil_destroy_tree_node_stack(extra_args.blockstack); __cil_ordered_lists_destroy(&extra_args.sidorder_lists); __cil_ordered_lists_destroy(&extra_args.classorder_lists); __cil_ordered_lists_destroy(&extra_args.catorder_lists); __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists); __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists); cil_list_destroy(&extra_args.in_list, CIL_FALSE); return rc; } static int __cil_resolve_name_with_root(struct cil_db *db, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; return cil_symtab_get_datum(symtab, name, datum); } static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; symtab_t *symtab = NULL; while (node != NULL && rc != SEPOL_OK) { switch (node->flavor) { case CIL_ROOT: goto exit; break; case CIL_BLOCK: symtab = &((struct cil_block*)node->data)->symtab[sym_index]; rc = cil_symtab_get_datum(symtab, name, datum); break; case CIL_BLOCKINHERIT: { struct cil_blockinherit *inherit = node->data; rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { /* Continue search in original block's parent */ rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum); goto exit; } } break; case CIL_MACRO: { struct cil_macro *macro = node->data; symtab = ¯o->symtab[sym_index]; rc = cil_symtab_get_datum(symtab, name, datum); } break; case CIL_CALL: { struct cil_call *call = node->data; rc = cil_resolve_name_call_args(call, name, sym_index, datum); if (rc != SEPOL_OK) { /* Continue search in macro's parent */ rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum); } } break; case CIL_IN: /* In block symtabs only exist before resolving the AST */ case CIL_CONDBLOCK: /* Cond block symtabs only exist before resolving the AST */ default: break; } node = node->parent; } exit: return rc; } static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; rc = __cil_resolve_name_with_parents(node, name, sym_index, datum); if (rc != SEPOL_OK) { rc = __cil_resolve_name_with_root(db, name, sym_index, datum); } return rc; } int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; struct cil_tree_node *node = NULL; rc = cil_resolve_name_keep_aliases(ast_node, name, sym_index, extra_args, datum); if (rc != SEPOL_OK) { goto exit; } /* If this datum is an alias, then return the actual node * This depends on aliases already being processed */ node = NODE(*datum); if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS || node->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)(*datum); if (alias->actual) { *datum = alias->actual; } } rc = SEPOL_OK; exit: return rc; } int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; struct cil_args_resolve *args = extra_args; struct cil_db *db = args->db; struct cil_tree_node *node = NULL; if (name == NULL) { cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n"); goto exit; } *datum = NULL; if (strchr(name,'.') == NULL) { /* No '.' in name */ rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { goto exit; } } else { char *sp = NULL; char *name_dup = cil_strdup(name); char *current = strtok_r(name_dup, ".", &sp); char *next = strtok_r(NULL, ".", &sp); symtab_t *symtab = NULL; if (current == NULL) { /* Only dots */ cil_tree_log(ast_node, CIL_ERR, "Invalid name %s", name); free(name_dup); goto exit; } node = ast_node; if (*name == '.') { /* Leading '.' */ symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_BLOCKS]; } else { rc = __cil_resolve_name_helper(db, node->parent, current, CIL_SYM_BLOCKS, datum); if (rc != SEPOL_OK) { free(name_dup); goto exit; } symtab = (*datum)->symtab; } /* Keep looking up blocks by name until only last part of name remains */ while (next != NULL) { rc = cil_symtab_get_datum(symtab, current, datum); if (rc != SEPOL_OK) { free(name_dup); goto exit; } node = NODE(*datum); if (node->flavor == CIL_BLOCK) { symtab = &((struct cil_block*)node->data)->symtab[CIL_SYM_BLOCKS]; } else { if (ast_node->flavor != CIL_IN) { cil_log(CIL_WARN, "Can only use %s name for name resolution in \"in\" blocks\n", cil_node_to_string(node)); free(name_dup); rc = SEPOL_ERR; goto exit; } if (node->flavor == CIL_MACRO) { struct cil_macro *macro = node->data; symtab = ¯o->symtab[sym_index]; } else { /* optional */ symtab = (*datum)->symtab; } } current = next; next = strtok_r(NULL, ".", &sp); } symtab = &(symtab[sym_index]); rc = cil_symtab_get_datum(symtab, current, datum); free(name_dup); if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: if (rc != SEPOL_OK) { *datum = NULL; } args->last_resolved_name = name; return rc; } libsepol/cil/src/cil_resolve_ast.h0100644 0000000 0000000 00000016050 13756670065 016323 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_RESOLVE_AST_H_ #define CIL_RESOLVE_AST_H_ #include #include "cil_internal.h" #include "cil_tree.h" int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args); int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args); int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args); int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args); int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args); int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args); int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args); int cil_resolve_typealias(struct cil_tree_node *current, void *extra_args); int cil_resolve_typebounds(struct cil_tree_node *current, void *extra_args); int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args); int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args); int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args); int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args); int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args); int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args); int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args); int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args); int cil_resolve_userbounds(struct cil_tree_node *current, void *extra_args); int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args); int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args); int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args); int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args); int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args); int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args); int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args); int cil_resolve_rolebounds(struct cil_tree_node *current, void *extra_args); int cil_resolve_sensalias(struct cil_tree_node *current, void *extra_args); int cil_resolve_catalias(struct cil_tree_node *current, void *extra_args); int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args); int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args); int cil_resolve_cat_list(struct cil_tree_node *current, struct cil_list *cat_list, struct cil_list *res_cat_list, void *extra_args); int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args); int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args); int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args); int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *levelrange, void *extra_args); int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args); int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args); int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args); int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args); int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args); int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args); int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args); int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args); int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args); int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args); int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args); int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args); int cil_resolve_blockinherit(struct cil_tree_node *current, void *extra_args); int cil_resolve_in(struct cil_tree_node *current, void *extra_args); int cil_resolve_call1(struct cil_tree_node *current, void *extra_args); int cil_resolve_call2(struct cil_tree_node *, void *extra_args); int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum); int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args); int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args); int cil_evaluate_expr(struct cil_list *datum_expr, uint16_t *result); int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args); int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current); int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum); int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum); #endif /* CIL_RESOLVE_AST_H_ */ libsepol/cil/src/cil_stack.c0100644 0000000 0000000 00000006170 13756670065 015077 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_stack.h" #define CIL_STACK_INIT_SIZE 16 void cil_stack_init(struct cil_stack **stack) { struct cil_stack *new_stack = cil_malloc(sizeof(*new_stack)); new_stack->stack = cil_malloc(sizeof(*(new_stack->stack)) * CIL_STACK_INIT_SIZE); new_stack->size = CIL_STACK_INIT_SIZE; new_stack->pos = -1; *stack = new_stack; } void cil_stack_destroy(struct cil_stack **stack) { if (stack == NULL || *stack == NULL) { return; } free((*stack)->stack); free(*stack); *stack = NULL; } void cil_stack_empty(struct cil_stack *stack) { stack->pos = -1; } int cil_stack_is_empty(struct cil_stack *stack) { return (stack->pos == -1); } void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data) { stack->pos++; if (stack->pos == stack->size) { stack->size *= 2; stack->stack = cil_realloc(stack->stack, sizeof(*stack->stack) * stack->size); } stack->stack[stack->pos].flavor = flavor; stack->stack[stack->pos].data = data; } struct cil_stack_item *cil_stack_pop(struct cil_stack *stack) { if (stack->pos == -1) { return NULL; } stack->pos--; return &stack->stack[stack->pos + 1]; } struct cil_stack_item *cil_stack_peek(struct cil_stack *stack) { if (stack->pos < 0) { return NULL; } return &stack->stack[stack->pos]; } struct cil_stack_item *cil_stack_peek_at(struct cil_stack *stack, int pos) { int peekpos = stack->pos - pos; if (peekpos < 0 || peekpos > stack->pos) { return NULL; } return &stack->stack[peekpos]; } libsepol/cil/src/cil_stack.h0100644 0000000 0000000 00000005007 13756670065 015102 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_STACK_H_ #define CIL_STACK_H_ struct cil_stack { struct cil_stack_item *stack; int size; int pos; }; struct cil_stack_item { enum cil_flavor flavor; void *data; }; #define cil_stack_for_each_starting_at(stack, start, pos, item) \ for (pos = start, item = cil_stack_peek_at(stack, pos); item != NULL; pos++, item = cil_stack_peek_at(stack, pos)) #define cil_stack_for_each(stack, pos, item) cil_stack_for_each_starting_at(stack, 0, pos, item) void cil_stack_init(struct cil_stack **stack); void cil_stack_destroy(struct cil_stack **stack); void cil_stack_empty(struct cil_stack *stack); int cil_stack_is_empty(struct cil_stack *stack); void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data); struct cil_stack_item *cil_stack_pop(struct cil_stack *stack); struct cil_stack_item *cil_stack_peek(struct cil_stack *stack); struct cil_stack_item *cil_stack_peek_at(struct cil_stack *stack, int pos); #endif libsepol/cil/src/cil_strpool.c0100644 0000000 0000000 00000010141 13756670065 015465 0ustar000000000 0000000 /* * Copyright 2014 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_mem.h" #include "cil_strpool.h" #include "cil_log.h" #define CIL_STRPOOL_TABLE_SIZE 1 << 15 struct cil_strpool_entry { char *str; }; static pthread_mutex_t cil_strpool_mutex = PTHREAD_MUTEX_INITIALIZER; static unsigned int cil_strpool_readers = 0; static hashtab_t cil_strpool_tab = NULL; static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key) { const char *p, *keyp; size_t size; unsigned int val; val = 0; keyp = (const char*)key; size = strlen(keyp); for (p = keyp; ((size_t) (p - keyp)) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (h->size - 1); } static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const char *keyp1 = (const char*)key1; const char *keyp2 = (const char*)key2; return strcmp(keyp1, keyp2); } char *cil_strpool_add(const char *str) { struct cil_strpool_entry *strpool_ref = NULL; pthread_mutex_lock(&cil_strpool_mutex); strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str); if (strpool_ref == NULL) { strpool_ref = cil_malloc(sizeof(*strpool_ref)); strpool_ref->str = cil_strdup(str); int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); if (rc != SEPOL_OK) { pthread_mutex_unlock(&cil_strpool_mutex); (*cil_mem_error_handler)(); pthread_mutex_lock(&cil_strpool_mutex); } } pthread_mutex_unlock(&cil_strpool_mutex); return strpool_ref->str; } static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused))) { struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry*)d; free(strpool_ref->str); free(strpool_ref); return SEPOL_OK; } void cil_strpool_init(void) { pthread_mutex_lock(&cil_strpool_mutex); if (cil_strpool_tab == NULL) { cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE); if (cil_strpool_tab == NULL) { pthread_mutex_unlock(&cil_strpool_mutex); (*cil_mem_error_handler)(); return; } } cil_strpool_readers++; pthread_mutex_unlock(&cil_strpool_mutex); } void cil_strpool_destroy(void) { pthread_mutex_lock(&cil_strpool_mutex); cil_strpool_readers--; if (cil_strpool_readers == 0) { hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); hashtab_destroy(cil_strpool_tab); cil_strpool_tab = NULL; } pthread_mutex_unlock(&cil_strpool_mutex); } libsepol/cil/src/cil_strpool.h0100644 0000000 0000000 00000003441 13756670065 015477 0ustar000000000 0000000 /* * Copyright 2014 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_STRPOOL_H_ #define CIL_STRPOOL_H_ #include char *cil_strpool_add(const char *str); void cil_strpool_init(void); void cil_strpool_destroy(void); #endif /* CIL_STRPOOL_H_ */ libsepol/cil/src/cil_symtab.c0100644 0000000 0000000 00000017205 13756670065 015272 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include "cil_internal.h" #include "cil_tree.h" #include "cil_symtab.h" #include "cil_mem.h" #include "cil_strpool.h" #include "cil_log.h" __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_symtab_error(const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(CIL_ERR, msg, ap); va_end(ap); exit(1); } void cil_symtab_init(symtab_t *symtab, unsigned int size) { int rc = symtab_init(symtab, size); if (rc != SEPOL_OK) { cil_symtab_error("Failed to create symtab\n"); } } void cil_symtab_datum_init(struct cil_symtab_datum *datum) { datum->name = NULL; datum->fqn = NULL; datum->symtab = NULL; cil_list_init(&datum->nodes, CIL_LIST_ITEM); } void cil_symtab_datum_destroy(struct cil_symtab_datum *datum) { cil_list_destroy(&datum->nodes, 0); cil_symtab_remove_datum(datum); } void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node) { if (datum && datum->nodes != NULL) { cil_list_remove(datum->nodes, CIL_NODE, node, 0); if (datum->nodes->head == NULL) { cil_symtab_datum_destroy(datum); } } } /* This both initializes the datum and inserts it into the symtab. Note that cil_symtab_datum_destroy() is the analog to the initializer portion */ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node) { int rc = hashtab_insert(symtab->table, key, (hashtab_datum_t)datum); if (rc == SEPOL_OK) { datum->name = key; datum->fqn = key; datum->symtab = symtab; cil_list_append(datum->nodes, CIL_NODE, node); } else if (rc == SEPOL_EEXIST) { cil_list_append(datum->nodes, CIL_NODE, node); } else { cil_symtab_error("Failed to insert datum into hashtab\n"); } return rc; } void cil_symtab_remove_datum(struct cil_symtab_datum *datum) { symtab_t *symtab = datum->symtab; if (symtab == NULL) { return; } hashtab_remove(symtab->table, datum->name, NULL, NULL); datum->symtab = NULL; } int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum) { *datum = (struct cil_symtab_datum*)hashtab_search(symtab->table, (hashtab_key_t)key); if (*datum == NULL) { return SEPOL_ENOENT; } return SEPOL_OK; } int cil_symtab_map(symtab_t *symtab, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { return hashtab_map(symtab->table, apply, args); } static int __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, __attribute__((unused)) void *args) { struct cil_symtab_datum *datum = d; datum->symtab = NULL; return SEPOL_OK; } void cil_symtab_destroy(symtab_t *symtab) { if (symtab->table != NULL){ cil_symtab_map(symtab, __cil_symtab_destroy_helper, NULL); hashtab_destroy(symtab->table); symtab->table = NULL; } } void cil_complex_symtab_hash(struct cil_complex_symtab_key *ckey, int mask, intptr_t *hash) { intptr_t sum = ckey->key1 + ckey->key2 + ckey->key3 + ckey->key4; *hash = (intptr_t)((sum >> 2) & mask); } void cil_complex_symtab_init(struct cil_complex_symtab *symtab, unsigned int size) { symtab->htable = cil_calloc(size, sizeof(struct cil_complex_symtab *)); symtab->nelems = 0; symtab->nslots = size; symtab->mask = size - 1; } int cil_complex_symtab_insert(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum *datum) { intptr_t hash; struct cil_complex_symtab_node *node = NULL; struct cil_complex_symtab_node *prev = NULL; struct cil_complex_symtab_node *curr = NULL; node = cil_malloc(sizeof(*node)); memset(node, 0, sizeof(*node)); node->ckey = ckey; node->datum = datum; cil_complex_symtab_hash(ckey, symtab->mask, &hash); for (prev = NULL, curr = symtab->htable[hash]; curr != NULL; prev = curr, curr = curr->next) { if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 == curr->ckey->key4) { free(node); return SEPOL_EEXIST; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 < curr->ckey->key2) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 < curr->ckey->key3) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 < curr->ckey->key4) { break; } } if (prev != NULL) { node->next = prev->next; prev->next = node; } else { node->next = symtab->htable[hash]; symtab->htable[hash] = node; } symtab->nelems++; return SEPOL_OK; } void cil_complex_symtab_search(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum **out) { intptr_t hash; struct cil_complex_symtab_node *curr = NULL; cil_complex_symtab_hash(ckey, symtab->mask, &hash); for (curr = symtab->htable[hash]; curr != NULL; curr = curr->next) { if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 == curr->ckey->key4) { *out = curr->datum; return; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 < curr->ckey->key2) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 < curr->ckey->key3) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 < curr->ckey->key4) { break; } } *out = NULL; } void cil_complex_symtab_destroy(struct cil_complex_symtab *symtab) { struct cil_complex_symtab_node *curr = NULL; struct cil_complex_symtab_node *temp = NULL; unsigned int i; if (symtab == NULL) { return; } for (i = 0; i < symtab->nslots; i++) { curr = symtab->htable[i]; while (curr != NULL) { temp = curr; curr = curr->next; free(temp); } symtab->htable[i] = NULL; } free(symtab->htable); symtab->htable = NULL; symtab->nelems = 0; symtab->nslots = 0; symtab->mask = 0; } libsepol/cil/src/cil_symtab.h0100644 0000000 0000000 00000007031 13756670065 015273 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef __CIL_SYMTAB_H_ #define __CIL_SYMTAB_H_ #include #include #include "cil_tree.h" struct cil_symtab_datum { struct cil_list *nodes; char *name; char *fqn; symtab_t *symtab; }; #define DATUM(d) ((struct cil_symtab_datum *)(d)) #define NODE(n) ((struct cil_tree_node *)(DATUM(n)->nodes->head->data)) #define FLAVOR(f) (NODE(f)->flavor) struct cil_complex_symtab_key { intptr_t key1; intptr_t key2; intptr_t key3; intptr_t key4; }; struct cil_complex_symtab_datum { void *data; }; struct cil_complex_symtab_node { struct cil_complex_symtab_key *ckey; struct cil_complex_symtab_datum *datum; struct cil_complex_symtab_node *next; }; struct cil_complex_symtab { struct cil_complex_symtab_node **htable; uint32_t nelems; uint32_t nslots; uint32_t mask; }; void cil_symtab_init(symtab_t *symtab, unsigned int size); void cil_symtab_datum_init(struct cil_symtab_datum *datum); void cil_symtab_datum_destroy(struct cil_symtab_datum *datum); void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node); int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node); void cil_symtab_remove_datum(struct cil_symtab_datum *datum); int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum); int cil_symtab_map(symtab_t *symtab, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); void cil_symtab_destroy(symtab_t *symtab); void cil_complex_symtab_init(struct cil_complex_symtab *symtab, unsigned int size); int cil_complex_symtab_insert(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum *datum); void cil_complex_symtab_search(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum **out); void cil_complex_symtab_destroy(struct cil_complex_symtab *symtab); #endif libsepol/cil/src/cil_tree.c0100644 0000000 0000000 00000132564 13756670065 014740 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_parser.h" #include "cil_strpool.h" void cil_tree_print_perms_list(struct cil_tree_node *current_perm); void cil_tree_print_classperms(struct cil_classperms *cp); void cil_tree_print_level(struct cil_level *level); void cil_tree_print_levelrange(struct cil_levelrange *lvlrange); void cil_tree_print_context(struct cil_context *context); void cil_tree_print_expr_tree(struct cil_tree_node *expr_root); void cil_tree_print_constrain(struct cil_constrain *cons); void cil_tree_print_node(struct cil_tree_node *node); __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(CIL_ERR, msg, ap); va_end(ap); exit(1); } struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil) { if (!node) { return NULL; } node = node->parent; while (node) { if (node->flavor == CIL_NODE && node->data == NULL) { if (node->cl_head->data == CIL_KEY_SRC_INFO) { /* Parse Tree */ *path = node->cl_head->next->next->data; *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL); return node; } node = node->parent; } else if (node->flavor == CIL_SRC_INFO) { /* AST */ struct cil_src_info *info = node->data; *path = info->path; *is_cil = info->is_cil; return node; } else { if (node->flavor == CIL_CALL) { struct cil_call *call = node->data; node = NODE(call->macro); } else if (node->flavor == CIL_BLOCKINHERIT) { struct cil_blockinherit *inherit = node->data; node = NODE(inherit->block); } else { node = node->parent; } } } return NULL; } char *cil_tree_get_cil_path(struct cil_tree_node *node) { char *path = NULL; int is_cil; while (node) { node = cil_tree_get_next_path(node, &path, &is_cil); if (node && is_cil) { return path; } } return NULL; } __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(lvl, msg, ap); va_end(ap); if (node) { char *path = NULL; int is_cil; unsigned hll_line = node->hll_line; path = cil_tree_get_cil_path(node); if (path != NULL) { cil_log(lvl, " at %s:%d", path, node->line); } while (node) { node = cil_tree_get_next_path(node, &path, &is_cil); if (node && !is_cil) { cil_log(lvl," from %s:%d", path, hll_line); path = NULL; hll_line = node->hll_line; } } } cil_log(lvl,"\n"); } int cil_tree_init(struct cil_tree **tree) { struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); cil_tree_node_init(&new_tree->root); *tree = new_tree; return SEPOL_OK; } void cil_tree_destroy(struct cil_tree **tree) { if (tree == NULL || *tree == NULL) { return; } cil_tree_subtree_destroy((*tree)->root); free(*tree); *tree = NULL; } void cil_tree_subtree_destroy(struct cil_tree_node *node) { cil_tree_children_destroy(node); cil_tree_node_destroy(&node); } void cil_tree_children_destroy(struct cil_tree_node *node) { struct cil_tree_node *start_node = node; struct cil_tree_node *next = NULL; if (node == NULL) { return; } if (node->cl_head != NULL) { node = node->cl_head; } while (node != start_node) { if (node->cl_head != NULL){ next = node->cl_head; } else { if (node->next == NULL) { next = node->parent; if (node->parent != NULL) { node->parent->cl_head = NULL; } cil_tree_node_destroy(&node); } else { next = node->next; cil_tree_node_destroy(&node); } } node = next; } } void cil_tree_node_init(struct cil_tree_node **node) { struct cil_tree_node *new_node = cil_malloc(sizeof(*new_node)); new_node->cl_head = NULL; new_node->cl_tail = NULL; new_node->parent = NULL; new_node->data = NULL; new_node->next = NULL; new_node->flavor = CIL_ROOT; new_node->line = 0; new_node->hll_line = 0; *node = new_node; } void cil_tree_node_destroy(struct cil_tree_node **node) { struct cil_symtab_datum *datum; if (node == NULL || *node == NULL) { return; } if ((*node)->flavor >= CIL_MIN_DECLARATIVE) { datum = (*node)->data; cil_symtab_datum_remove_node(datum, *node); if (datum->nodes == NULL) { cil_destroy_data(&(*node)->data, (*node)->flavor); } } else { cil_destroy_data(&(*node)->data, (*node)->flavor); } free(*node); *node = NULL; } /* Perform depth-first walk of the tree Parameters: start_node: root node to start walking from process_node: function to call when visiting a node Takes parameters: node: node being visited finished: boolean indicating to the tree walker that it should move on from this branch extra_args: additional data first_child: Function to call before entering list of children Takes parameters: node: node of first child extra args: additional data last_child: Function to call when finished with the last child of a node's children extra_args: any additional data to be passed to the helper functions */ int cil_tree_walk_core(struct cil_tree_node *node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args) { int rc = SEPOL_ERR; while (node) { uint32_t finished = CIL_TREE_SKIP_NOTHING; if (process_node != NULL) { rc = (*process_node)(node, &finished, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } if (finished & CIL_TREE_SKIP_NEXT) { return SEPOL_OK; } if (node->cl_head != NULL && !(finished & CIL_TREE_SKIP_HEAD)) { rc = cil_tree_walk(node, process_node, first_child, last_child, extra_args); if (rc != SEPOL_OK) { return rc; } } node = node->next; } return SEPOL_OK; } int cil_tree_walk(struct cil_tree_node *node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args) { int rc = SEPOL_ERR; if (!node || !node->cl_head) { return SEPOL_OK; } if (first_child != NULL) { rc = (*first_child)(node->cl_head, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } rc = cil_tree_walk_core(node->cl_head, process_node, first_child, last_child, extra_args); if (rc != SEPOL_OK) { return rc; } if (last_child != NULL) { rc = (*last_child)(node->cl_tail, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } return SEPOL_OK; } /* Copied from cil_policy.c, but changed to prefix -- Need to refactor */ static int cil_expr_to_string(struct cil_list *expr, char **out) { int rc = SEPOL_ERR; struct cil_list_item *curr; char *stack[COND_EXPR_MAXDEPTH] = {}; int pos = 0; cil_list_for_each(curr, expr) { if (pos >= COND_EXPR_MAXDEPTH) { rc = SEPOL_ERR; goto exit; } switch (curr->flavor) { case CIL_LIST: rc = cil_expr_to_string(curr->data, &stack[pos]); if (rc != SEPOL_OK) { goto exit; } pos++; break; case CIL_STRING: stack[pos] = curr->data; pos++; break; case CIL_DATUM: stack[pos] = ((struct cil_symtab_datum *)curr->data)->name; pos++; break; case CIL_OP: { int len; char *expr_str; enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data); char *op_str = NULL; if (pos == 0) { rc = SEPOL_ERR; goto exit; } switch (op_flavor) { case CIL_AND: op_str = CIL_KEY_AND; break; case CIL_OR: op_str = CIL_KEY_OR; break; case CIL_NOT: op_str = CIL_KEY_NOT; break; case CIL_ALL: op_str = CIL_KEY_ALL; break; case CIL_EQ: op_str = CIL_KEY_EQ; break; case CIL_NEQ: op_str = CIL_KEY_NEQ; break; case CIL_XOR: op_str = CIL_KEY_XOR; break; case CIL_RANGE: op_str = CIL_KEY_RANGE; break; case CIL_CONS_DOM: op_str = CIL_KEY_CONS_DOM; break; case CIL_CONS_DOMBY: op_str = CIL_KEY_CONS_DOMBY; break; case CIL_CONS_INCOMP: op_str = CIL_KEY_CONS_INCOMP; break; default: cil_log(CIL_ERR, "Unknown operator in expression\n"); goto exit; break; } if (op_flavor == CIL_NOT) { len = strlen(stack[pos-1]) + strlen(op_str) + 4; expr_str = cil_malloc(len); snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]); free(stack[pos-1]); stack[pos-1] = NULL; pos--; } else { if (pos < 2) { rc = SEPOL_ERR; goto exit; } len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5; expr_str = cil_malloc(len); snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]); free(stack[pos-2]); free(stack[pos-1]); stack[pos-2] = NULL; stack[pos-1] = NULL; pos -= 2; } stack[pos] = expr_str; pos++; break; } case CIL_CONS_OPERAND: { enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data); char *operand_str = NULL; switch (operand_flavor) { case CIL_CONS_U1: operand_str = CIL_KEY_CONS_U1; break; case CIL_CONS_U2: operand_str = CIL_KEY_CONS_U2; break; case CIL_CONS_U3: operand_str = CIL_KEY_CONS_U3; break; case CIL_CONS_T1: operand_str = CIL_KEY_CONS_T1; break; case CIL_CONS_T2: operand_str = CIL_KEY_CONS_T2; break; case CIL_CONS_T3: operand_str = CIL_KEY_CONS_T3; break; case CIL_CONS_R1: operand_str = CIL_KEY_CONS_R1; break; case CIL_CONS_R2: operand_str = CIL_KEY_CONS_R2; break; case CIL_CONS_R3: operand_str = CIL_KEY_CONS_R3; break; case CIL_CONS_L1: operand_str = CIL_KEY_CONS_L1; break; case CIL_CONS_L2: operand_str = CIL_KEY_CONS_L2; break; case CIL_CONS_H1: operand_str = CIL_KEY_CONS_H1; break; case CIL_CONS_H2: operand_str = CIL_KEY_CONS_H2; break; default: cil_log(CIL_ERR, "Unknown operand in expression\n"); goto exit; break; } stack[pos] = operand_str; pos++; break; } default: cil_log(CIL_ERR, "Unknown flavor in expression\n"); goto exit; break; } } *out = stack[0]; return SEPOL_OK; exit: return rc; } void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr) { char *expr_str; int rc; cil_log(CIL_INFO, "("); if (datum_expr != NULL) { rc = cil_expr_to_string(datum_expr, &expr_str); } else { rc = cil_expr_to_string(str_expr, &expr_str); } if (rc != SEPOL_OK) { cil_log(CIL_INFO, "ERROR)"); return; } cil_log(CIL_INFO, "%s)", expr_str); free(expr_str); } void cil_tree_print_perms_list(struct cil_tree_node *current_perm) { while (current_perm != NULL) { if (current_perm->flavor == CIL_PERM) { cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name); } else if (current_perm->flavor == CIL_MAP_PERM) { cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name); } else { cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor); break; } current_perm = current_perm->next; } } void cil_tree_print_cats(struct cil_cats *cats) { cil_tree_print_expr(cats->datum_expr, cats->str_expr); } void cil_tree_print_perm_strs(struct cil_list *perm_strs) { struct cil_list_item *curr; if (perm_strs == NULL) { return; } cil_log(CIL_INFO, " ("); cil_list_for_each(curr, perm_strs) { cil_log(CIL_INFO, " %s", (char*)curr->data); } cil_log(CIL_INFO, " )"); } void cil_tree_print_classperms(struct cil_classperms *cp) { if (cp == NULL) { return; } cil_log(CIL_INFO, " class: %s", cp->class_str); cil_log(CIL_INFO, ", perm_strs:"); cil_tree_print_perm_strs(cp->perm_strs); } void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set) { if (cp_set == NULL) { return; } cil_log(CIL_INFO, " %s", cp_set->set_str); } void cil_tree_print_classperms_list(struct cil_list *cp_list) { struct cil_list_item *i; if (cp_list == NULL) { return; } cil_list_for_each(i, cp_list) { if (i->flavor == CIL_CLASSPERMS) { cil_tree_print_classperms(i->data); } else { cil_tree_print_classperms_set(i->data); } } } void cil_tree_print_level(struct cil_level *level) { if (level->sens != NULL) { cil_log(CIL_INFO, " %s", level->sens->datum.name); } else if (level->sens_str != NULL) { cil_log(CIL_INFO, " %s", level->sens_str); } cil_tree_print_cats(level->cats); return; } void cil_tree_print_levelrange(struct cil_levelrange *lvlrange) { cil_log(CIL_INFO, " ("); if (lvlrange->low != NULL) { cil_log(CIL_INFO, " ("); cil_tree_print_level(lvlrange->low); cil_log(CIL_INFO, " )"); } else if (lvlrange->low_str != NULL) { cil_log(CIL_INFO, " %s", lvlrange->low_str); } if (lvlrange->high != NULL) { cil_log(CIL_INFO, " ("); cil_tree_print_level(lvlrange->high); cil_log(CIL_INFO, " )"); } else if (lvlrange->high_str != NULL) { cil_log(CIL_INFO, " %s", lvlrange->high_str); } cil_log(CIL_INFO, " )"); } void cil_tree_print_context(struct cil_context *context) { cil_log(CIL_INFO, " ("); if (context->user != NULL) { cil_log(CIL_INFO, " %s", context->user->datum.name); } else if (context->user_str != NULL) { cil_log(CIL_INFO, " %s", context->user_str); } if (context->role != NULL) { cil_log(CIL_INFO, " %s", context->role->datum.name); } else if (context->role_str != NULL) { cil_log(CIL_INFO, " %s", context->role_str); } if (context->type != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name); } else if (context->type_str != NULL) { cil_log(CIL_INFO, " %s", context->type_str); } if (context->range != NULL) { cil_tree_print_levelrange(context->range); } else if (context->range_str != NULL) { cil_log(CIL_INFO, " %s", context->range_str); } cil_log(CIL_INFO, " )"); return; } void cil_tree_print_constrain(struct cil_constrain *cons) { cil_tree_print_classperms_list(cons->classperms); cil_tree_print_expr(cons->datum_expr, cons->str_expr); cil_log(CIL_INFO, "\n"); } void cil_tree_print_node(struct cil_tree_node *node) { if (node->data == NULL) { cil_log(CIL_INFO, "FLAVOR: %d", node->flavor); return; } else { switch( node->flavor ) { case CIL_BLOCK: { struct cil_block *block = node->data; cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name); return; } case CIL_BLOCKINHERIT: { struct cil_blockinherit *inherit = node->data; cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str); return; } case CIL_BLOCKABSTRACT: { struct cil_blockabstract *abstract = node->data; cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str); return; } case CIL_IN: { struct cil_in *in = node->data; cil_log(CIL_INFO, "IN: %s\n", in->block_str); return; } case CIL_USER: { struct cil_user *user = node->data; cil_log(CIL_INFO, "USER: %s\n", user->datum.name); return; } case CIL_TYPE: { struct cil_type *type = node->data; cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name); return; } case CIL_EXPANDTYPEATTRIBUTE: { struct cil_expandtypeattribute *attr = node->data; fprintf(stderr, "%s %u\n", __func__, __LINE__); cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE "); cil_tree_print_expr(attr->attr_datums, attr->attr_strs); cil_log(CIL_INFO, "%s)\n",attr->expand ? CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE); return; } case CIL_TYPEATTRIBUTESET: { struct cil_typeattributeset *attr = node->data; cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str); cil_tree_print_expr(attr->datum_expr, attr->str_expr); cil_log(CIL_INFO, "\n"); return; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name); return; } case CIL_ROLE: { struct cil_role *role = node->data; cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name); return; } case CIL_USERROLE: { struct cil_userrole *userrole = node->data; cil_log(CIL_INFO, "USERROLE:"); struct cil_symtab_datum *datum = NULL; if (userrole->user != NULL) { datum = userrole->user; cil_log(CIL_INFO, " %s", datum->name); } else if (userrole->user_str != NULL) { cil_log(CIL_INFO, " %s", userrole->user_str); } if (userrole->role != NULL) { datum = userrole->role; cil_log(CIL_INFO, " %s", datum->name); } else if (userrole->role_str != NULL) { cil_log(CIL_INFO, " %s", userrole->role_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_USERLEVEL: { struct cil_userlevel *usrlvl = node->data; cil_log(CIL_INFO, "USERLEVEL:"); if (usrlvl->user_str != NULL) { cil_log(CIL_INFO, " %s", usrlvl->user_str); } if (usrlvl->level != NULL) { cil_log(CIL_INFO, " ("); cil_tree_print_level(usrlvl->level); cil_log(CIL_INFO, " )"); } else if (usrlvl->level_str != NULL) { cil_log(CIL_INFO, " %s", usrlvl->level_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_USERRANGE: { struct cil_userrange *userrange = node->data; cil_log(CIL_INFO, "USERRANGE:"); if (userrange->user_str != NULL) { cil_log(CIL_INFO, " %s", userrange->user_str); } if (userrange->range != NULL) { cil_log(CIL_INFO, " ("); cil_tree_print_levelrange(userrange->range); cil_log(CIL_INFO, " )"); } else if (userrange->range_str != NULL) { cil_log(CIL_INFO, " %s", userrange->range_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_USERBOUNDS: { struct cil_bounds *bnds = node->data; cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); return; } case CIL_ROLETYPE: { struct cil_roletype *roletype = node->data; struct cil_symtab_datum *datum = NULL; cil_log(CIL_INFO, "ROLETYPE:"); if (roletype->role != NULL) { datum = roletype->role; cil_log(CIL_INFO, " %s", datum->name); } else if (roletype->role_str != NULL) { cil_log(CIL_INFO, " %s", roletype->role_str); } if (roletype->type != NULL) { datum = roletype->type; cil_log(CIL_INFO, " %s", datum->name); } else if (roletype->type_str != NULL) { cil_log(CIL_INFO, " %s", roletype->type_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_ROLETRANSITION: { struct cil_roletransition *roletrans = node->data; cil_log(CIL_INFO, "ROLETRANSITION:"); if (roletrans->src != NULL) { cil_log(CIL_INFO, " %s", roletrans->src->datum.name); } else { cil_log(CIL_INFO, " %s", roletrans->src_str); } if (roletrans->tgt != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name); } else { cil_log(CIL_INFO, " %s", roletrans->tgt_str); } if (roletrans->obj != NULL) { cil_log(CIL_INFO, " %s", roletrans->obj->datum.name); } else { cil_log(CIL_INFO, " %s", roletrans->obj_str); } if (roletrans->result != NULL) { cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name); } else { cil_log(CIL_INFO, " %s\n", roletrans->result_str); } return; } case CIL_ROLEALLOW: { struct cil_roleallow *roleallow = node->data; cil_log(CIL_INFO, "ROLEALLOW:"); if (roleallow->src != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name); } else { cil_log(CIL_INFO, " %s", roleallow->src_str); } if (roleallow->tgt != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name); } else { cil_log(CIL_INFO, " %s", roleallow->tgt_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_ROLEATTRIBUTESET: { struct cil_roleattributeset *attr = node->data; cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str); cil_tree_print_expr(attr->datum_expr, attr->str_expr); cil_log(CIL_INFO, "\n"); return; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = node->data; cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name); return; } case CIL_USERATTRIBUTESET: { struct cil_userattributeset *attr = node->data; cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str); cil_tree_print_expr(attr->datum_expr, attr->str_expr); cil_log(CIL_INFO, "\n"); return; } case CIL_USERATTRIBUTE: { struct cil_userattribute *attr = node->data; cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name); return; } case CIL_ROLEBOUNDS: { struct cil_bounds *bnds = node->data; cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); return; } case CIL_CLASS: { struct cil_class *cls = node->data; cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name); if (cls->common != NULL) { cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name); } cil_log(CIL_INFO, "("); cil_tree_print_perms_list(node->cl_head); cil_log(CIL_INFO, " )"); return; } case CIL_CLASSORDER: { struct cil_classorder *classorder = node->data; struct cil_list_item *class; if (classorder->class_list_str == NULL) { cil_log(CIL_INFO, "CLASSORDER: ()\n"); return; } cil_log(CIL_INFO, "CLASSORDER: ("); cil_list_for_each(class, classorder->class_list_str) { cil_log(CIL_INFO, " %s", (char*)class->data); } cil_log(CIL_INFO, " )\n"); return; } case CIL_COMMON: { struct cil_class *common = node->data; cil_log(CIL_INFO, "COMMON: %s (", common->datum.name); cil_tree_print_perms_list(node->cl_head); cil_log(CIL_INFO, " )"); return; } case CIL_CLASSCOMMON: { struct cil_classcommon *clscom = node->data; cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str); return; } case CIL_CLASSPERMISSION: { struct cil_classpermission *cp = node->data; cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name); cil_log(CIL_INFO, "\n"); return; } case CIL_CLASSPERMISSIONSET: { struct cil_classpermissionset *cps = node->data; cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str); cil_tree_print_classperms_list(cps->classperms); cil_log(CIL_INFO, "\n"); return; } case CIL_MAP_CLASS: { struct cil_class *cm = node->data; cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name); cil_log(CIL_INFO, " ("); cil_tree_print_perms_list(node->cl_head); cil_log(CIL_INFO, " )\n"); return; } case CIL_MAP_PERM: { struct cil_perm *cmp = node->data; cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name); if (cmp->classperms == NULL) { cil_log(CIL_INFO, " perms: ()"); return; } cil_log(CIL_INFO, " kernel class perms: ("); cil_tree_print_classperms_list(cmp->classperms); cil_log(CIL_INFO, " )\n"); return; } case CIL_CLASSMAPPING: { struct cil_classmapping *mapping = node->data; cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str); cil_log(CIL_INFO, " ("); cil_tree_print_classperms_list(mapping->classperms); cil_log(CIL_INFO, " )\n"); return; } case CIL_BOOL: { struct cil_bool *boolean = node->data; cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value); return; } case CIL_TUNABLE: { struct cil_tunable *tunable = node->data; cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value); return; } case CIL_BOOLEANIF: { struct cil_booleanif *bif = node->data; cil_log(CIL_INFO, "(BOOLEANIF "); cil_tree_print_expr(bif->datum_expr, bif->str_expr); cil_log(CIL_INFO, " )\n"); return; } case CIL_TUNABLEIF: { struct cil_tunableif *tif = node->data; cil_log(CIL_INFO, "(TUNABLEIF "); cil_tree_print_expr(tif->datum_expr, tif->str_expr); cil_log(CIL_INFO, " )\n"); return; } case CIL_CONDBLOCK: { struct cil_condblock *cb = node->data; if (cb->flavor == CIL_CONDTRUE) { cil_log(CIL_INFO, "true\n"); } else if (cb->flavor == CIL_CONDFALSE) { cil_log(CIL_INFO, "false\n"); } return; } case CIL_ALL: cil_log(CIL_INFO, "all"); return; case CIL_AND: cil_log(CIL_INFO, "&&"); return; case CIL_OR: cil_log(CIL_INFO, "|| "); return; case CIL_NOT: cil_log(CIL_INFO, "!"); return; case CIL_EQ: cil_log(CIL_INFO, "=="); return; case CIL_NEQ: cil_log(CIL_INFO, "!="); return; case CIL_TYPEALIAS: { struct cil_alias *alias = node->data; cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name); return; } case CIL_TYPEALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str); return; } case CIL_TYPEBOUNDS: { struct cil_bounds *bnds = node->data; cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); return; } case CIL_TYPEPERMISSIVE: { struct cil_typepermissive *typeperm = node->data; if (typeperm->type != NULL) { cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name); } else { cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str); } return; } case CIL_NAMETYPETRANSITION: { struct cil_nametypetransition *nametypetrans = node->data; cil_log(CIL_INFO, "TYPETRANSITION:"); if (nametypetrans->src != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name); } else { cil_log(CIL_INFO, " %s", nametypetrans->src_str); } if (nametypetrans->tgt != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name); } else { cil_log(CIL_INFO, " %s", nametypetrans->tgt_str); } if (nametypetrans->obj != NULL) { cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name); } else { cil_log(CIL_INFO, " %s", nametypetrans->obj_str); } cil_log(CIL_INFO, " %s\n", nametypetrans->name_str); if (nametypetrans->result != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name); } else { cil_log(CIL_INFO, " %s", nametypetrans->result_str); } return; } case CIL_RANGETRANSITION: { struct cil_rangetransition *rangetrans = node->data; cil_log(CIL_INFO, "RANGETRANSITION:"); if (rangetrans->src != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name); } else { cil_log(CIL_INFO, " %s", rangetrans->src_str); } if (rangetrans->exec != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name); } else { cil_log(CIL_INFO, " %s", rangetrans->exec_str); } if (rangetrans->obj != NULL) { cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name); } else { cil_log(CIL_INFO, " %s", rangetrans->obj_str); } if (rangetrans->range != NULL) { cil_log(CIL_INFO, " ("); cil_tree_print_levelrange(rangetrans->range); cil_log(CIL_INFO, " )"); } else { cil_log(CIL_INFO, " %s", rangetrans->range_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_AVRULE: { struct cil_avrule *rule = node->data; switch (rule->rule_kind) { case CIL_AVRULE_ALLOWED: cil_log(CIL_INFO, "ALLOW:"); break; case CIL_AVRULE_AUDITALLOW: cil_log(CIL_INFO, "AUDITALLOW:"); break; case CIL_AVRULE_DONTAUDIT: cil_log(CIL_INFO, "DONTAUDIT:"); break; case CIL_AVRULE_NEVERALLOW: cil_log(CIL_INFO, "NEVERALLOW:"); break; } if (rule->src != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name); } else { cil_log(CIL_INFO, " %s", rule->src_str); } if (rule->tgt != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name); } else { cil_log(CIL_INFO, " %s", rule->tgt_str); } cil_tree_print_classperms_list(rule->perms.classperms); cil_log(CIL_INFO, "\n"); return; } case CIL_TYPE_RULE: { struct cil_type_rule *rule = node->data; switch (rule->rule_kind) { case CIL_TYPE_TRANSITION: cil_log(CIL_INFO, "TYPETRANSITION:"); break; case CIL_TYPE_MEMBER: cil_log(CIL_INFO, "TYPEMEMBER:"); break; case CIL_TYPE_CHANGE: cil_log(CIL_INFO, "TYPECHANGE:"); break; } if (rule->src != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name); } else { cil_log(CIL_INFO, " %s", rule->src_str); } if (rule->tgt != NULL) { cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name); } else { cil_log(CIL_INFO, " %s", rule->tgt_str); } if (rule->obj != NULL) { cil_log(CIL_INFO, " %s", rule->obj->datum.name); } else { cil_log(CIL_INFO, " %s", rule->obj_str); } if (rule->result != NULL) { cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name); } else { cil_log(CIL_INFO, " %s\n", rule->result_str); } return; } case CIL_SENS: { struct cil_sens *sens = node->data; cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name); return; } case CIL_SENSALIAS: { struct cil_alias *alias = node->data; cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name); return; } case CIL_SENSALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str); return; } case CIL_CAT: { struct cil_cat *cat = node->data; cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name); return; } case CIL_CATALIAS: { struct cil_alias *alias = node->data; cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name); return; } case CIL_CATALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str); return; } case CIL_CATSET: { struct cil_catset *catset = node->data; cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name); cil_tree_print_cats(catset->cats); return; } case CIL_CATORDER: { struct cil_catorder *catorder = node->data; struct cil_list_item *cat; if (catorder->cat_list_str == NULL) { cil_log(CIL_INFO, "CATORDER: ()\n"); return; } cil_log(CIL_INFO, "CATORDER: ("); cil_list_for_each(cat, catorder->cat_list_str) { cil_log(CIL_INFO, " %s", (char*)cat->data); } cil_log(CIL_INFO, " )\n"); return; } case CIL_SENSCAT: { struct cil_senscat *senscat = node->data; cil_log(CIL_INFO, "SENSCAT: sens:"); if (senscat->sens_str != NULL) { cil_log(CIL_INFO, " %s ", senscat->sens_str); } else { cil_log(CIL_INFO, " [processed]"); } cil_tree_print_cats(senscat->cats); return; } case CIL_SENSITIVITYORDER: { struct cil_sensorder *sensorder = node->data; struct cil_list_item *sens; cil_log(CIL_INFO, "SENSITIVITYORDER: ("); if (sensorder->sens_list_str != NULL) { cil_list_for_each(sens, sensorder->sens_list_str) { if (sens->flavor == CIL_LIST) { struct cil_list_item *sub; cil_log(CIL_INFO, " ("); cil_list_for_each(sub, (struct cil_list*)sens->data) { cil_log(CIL_INFO, " %s", (char*)sub->data); } cil_log(CIL_INFO, " )"); } else { cil_log(CIL_INFO, " %s", (char*)sens->data); } } } cil_log(CIL_INFO, " )\n"); return; } case CIL_LEVEL: { struct cil_level *level = node->data; cil_log(CIL_INFO, "LEVEL %s:", level->datum.name); cil_tree_print_level(level); cil_log(CIL_INFO, "\n"); return; } case CIL_LEVELRANGE: { struct cil_levelrange *lvlrange = node->data; cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name); cil_tree_print_levelrange(lvlrange); cil_log(CIL_INFO, "\n"); return; } case CIL_CONSTRAIN: { struct cil_constrain *cons = node->data; cil_log(CIL_INFO, "CONSTRAIN: ("); cil_tree_print_constrain(cons); return; } case CIL_MLSCONSTRAIN: { struct cil_constrain *cons = node->data; cil_log(CIL_INFO, "MLSCONSTRAIN: ("); cil_tree_print_constrain(cons); return; } case CIL_VALIDATETRANS: { struct cil_validatetrans *vt = node->data; cil_log(CIL_INFO, "(VALIDATETRANS "); if (vt->class != NULL) { cil_log(CIL_INFO, "%s ", vt->class->datum.name); } else if (vt->class_str != NULL) { cil_log(CIL_INFO, "%s ", vt->class_str); } cil_tree_print_expr(vt->datum_expr, vt->str_expr); cil_log(CIL_INFO, ")\n"); return; } case CIL_MLSVALIDATETRANS: { struct cil_validatetrans *vt = node->data; cil_log(CIL_INFO, "(MLSVALIDATETRANS "); if (vt->class != NULL) { cil_log(CIL_INFO, "%s ", vt->class->datum.name); } else if (vt->class_str != NULL) { cil_log(CIL_INFO, "%s ", vt->class_str); } cil_tree_print_expr(vt->datum_expr, vt->str_expr); cil_log(CIL_INFO, ")\n"); return; } case CIL_CONTEXT: { struct cil_context *context = node->data; cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name); cil_tree_print_context(context); cil_log(CIL_INFO, "\n"); return; } case CIL_FILECON: { struct cil_filecon *filecon = node->data; cil_log(CIL_INFO, "FILECON:"); cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type); if (filecon->context != NULL) { cil_tree_print_context(filecon->context); } else if (filecon->context_str != NULL) { cil_log(CIL_INFO, " %s", filecon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_IBPKEYCON: { struct cil_ibpkeycon *ibpkeycon = node->data; cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str); cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high); if (ibpkeycon->context) cil_tree_print_context(ibpkeycon->context); else if (ibpkeycon->context_str) cil_log(CIL_INFO, " %s", ibpkeycon->context_str); cil_log(CIL_INFO, "\n"); return; } case CIL_PORTCON: { struct cil_portcon *portcon = node->data; cil_log(CIL_INFO, "PORTCON:"); if (portcon->proto == CIL_PROTOCOL_UDP) { cil_log(CIL_INFO, " udp"); } else if (portcon->proto == CIL_PROTOCOL_TCP) { cil_log(CIL_INFO, " tcp"); } else if (portcon->proto == CIL_PROTOCOL_DCCP) { cil_log(CIL_INFO, " dccp"); } else if (portcon->proto == CIL_PROTOCOL_SCTP) { cil_log(CIL_INFO, " sctp"); } cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high); if (portcon->context != NULL) { cil_tree_print_context(portcon->context); } else if (portcon->context_str != NULL) { cil_log(CIL_INFO, " %s", portcon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_NODECON: { struct cil_nodecon *nodecon = node->data; char buf[256]; cil_log(CIL_INFO, "NODECON:"); if (nodecon->addr) { inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256); cil_log(CIL_INFO, " %s", buf); } else { cil_log(CIL_INFO, " %s", nodecon->addr_str); } if (nodecon->mask) { inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256); cil_log(CIL_INFO, " %s", buf); } else { cil_log(CIL_INFO, " %s", nodecon->mask_str); } if (nodecon->context != NULL) { cil_tree_print_context(nodecon->context); } else if (nodecon->context_str != NULL) { cil_log(CIL_INFO, " %s", nodecon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_GENFSCON: { struct cil_genfscon *genfscon = node->data; cil_log(CIL_INFO, "GENFSCON:"); cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str); if (genfscon->context != NULL) { cil_tree_print_context(genfscon->context); } else if (genfscon->context_str != NULL) { cil_log(CIL_INFO, " %s", genfscon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_NETIFCON: { struct cil_netifcon *netifcon = node->data; cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str); if (netifcon->if_context != NULL) { cil_tree_print_context(netifcon->if_context); } else if (netifcon->if_context_str != NULL) { cil_log(CIL_INFO, " %s", netifcon->if_context_str); } if (netifcon->packet_context != NULL) { cil_tree_print_context(netifcon->packet_context); } else if (netifcon->packet_context_str != NULL) { cil_log(CIL_INFO, " %s", netifcon->packet_context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_IBENDPORTCON: { struct cil_ibendportcon *ibendportcon = node->data; cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port); if (ibendportcon->context) cil_tree_print_context(ibendportcon->context); else if (ibendportcon->context_str) cil_log(CIL_INFO, " %s", ibendportcon->context_str); cil_log(CIL_INFO, "\n"); return; } case CIL_PIRQCON: { struct cil_pirqcon *pirqcon = node->data; cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq); if (pirqcon->context != NULL) { cil_tree_print_context(pirqcon->context); } else { cil_log(CIL_INFO, " %s", pirqcon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_IOMEMCON: { struct cil_iomemcon *iomemcon = node->data; cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high); if (iomemcon->context != NULL) { cil_tree_print_context(iomemcon->context); } else { cil_log(CIL_INFO, " %s", iomemcon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_IOPORTCON: { struct cil_ioportcon *ioportcon = node->data; cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high); if (ioportcon->context != NULL) { cil_tree_print_context(ioportcon->context); } else { cil_log(CIL_INFO, " %s", ioportcon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_PCIDEVICECON: { struct cil_pcidevicecon *pcidevicecon = node->data; cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev); if (pcidevicecon->context != NULL) { cil_tree_print_context(pcidevicecon->context); } else { cil_log(CIL_INFO, " %s", pcidevicecon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_DEVICETREECON: { struct cil_devicetreecon *devicetreecon = node->data; cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path); if (devicetreecon->context != NULL) { cil_tree_print_context(devicetreecon->context); } else { cil_log(CIL_INFO, " %s", devicetreecon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_FSUSE: { struct cil_fsuse *fsuse = node->data; cil_log(CIL_INFO, "FSUSE: "); if (fsuse->type == CIL_FSUSE_XATTR) { cil_log(CIL_INFO, "xattr "); } else if (fsuse->type == CIL_FSUSE_TASK) { cil_log(CIL_INFO, "task "); } else if (fsuse->type == CIL_FSUSE_TRANS) { cil_log(CIL_INFO, "trans "); } else { cil_log(CIL_INFO, "unknown "); } cil_log(CIL_INFO, "%s ", fsuse->fs_str); if (fsuse->context != NULL) { cil_tree_print_context(fsuse->context); } else { cil_log(CIL_INFO, " %s", fsuse->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_SID: { struct cil_sid *sid = node->data; cil_log(CIL_INFO, "SID: %s\n", sid->datum.name); return; } case CIL_SIDCONTEXT: { struct cil_sidcontext *sidcon = node->data; cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str); if (sidcon->context != NULL) { cil_tree_print_context(sidcon->context); } else { cil_log(CIL_INFO, " %s", sidcon->context_str); } cil_log(CIL_INFO, "\n"); return; } case CIL_SIDORDER: { struct cil_sidorder *sidorder = node->data; struct cil_list_item *sid; if (sidorder->sid_list_str == NULL) { cil_log(CIL_INFO, "SIDORDER: ()\n"); return; } cil_log(CIL_INFO, "SIDORDER: ("); cil_list_for_each(sid, sidorder->sid_list_str) { cil_log(CIL_INFO, " %s", (char*)sid->data); } cil_log(CIL_INFO, " )\n"); return; } case CIL_POLICYCAP: { struct cil_policycap *polcap = node->data; cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name); return; } case CIL_MACRO: { struct cil_macro *macro = node->data; cil_log(CIL_INFO, "MACRO %s:", macro->datum.name); if (macro->params != NULL && macro->params->head != NULL) { struct cil_list_item *curr_param; cil_log(CIL_INFO, " parameters: ("); cil_list_for_each(curr_param, macro->params) { cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str); } cil_log(CIL_INFO, " )"); } cil_log(CIL_INFO, "\n"); return; } case CIL_CALL: { struct cil_call *call = node->data; cil_log(CIL_INFO, "CALL: macro name:"); if (call->macro != NULL) { cil_log(CIL_INFO, " %s", call->macro->datum.name); } else { cil_log(CIL_INFO, " %s", call->macro_str); } if (call->args != NULL) { cil_log(CIL_INFO, ", args: ( "); struct cil_list_item *item; cil_list_for_each(item, call->args) { struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg; if (datum != NULL) { if (datum->nodes != NULL && datum->nodes->head != NULL) { cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data); } } else if (((struct cil_args*)item->data)->arg_str != NULL) { switch (item->flavor) { case CIL_TYPE: cil_log(CIL_INFO, "type:"); break; case CIL_USER: cil_log(CIL_INFO, "user:"); break; case CIL_ROLE: cil_log(CIL_INFO, "role:"); break; case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break; case CIL_CAT: cil_log(CIL_INFO, "category:"); break; case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break; case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break; case CIL_CLASS: cil_log(CIL_INFO, "class:"); break; default: break; } cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str); } } cil_log(CIL_INFO, ")"); } cil_log(CIL_INFO, "\n"); return; } case CIL_OPTIONAL: { struct cil_optional *optional = node->data; cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name); return; } case CIL_IPADDR: { struct cil_ipaddr *ipaddr = node->data; char buf[256]; inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256); cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf); break; } default : { cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor); return; } } } } void cil_tree_print(struct cil_tree_node *tree, uint32_t depth) { struct cil_tree_node *current = NULL; current = tree; uint32_t x = 0; if (current != NULL) { if (current->cl_head == NULL) { if (current->flavor == CIL_NODE) { if (current->parent->cl_head == current) { cil_log(CIL_INFO, "%s", (char*)current->data); } else { cil_log(CIL_INFO, " %s", (char*)current->data); } } else if (current->flavor != CIL_PERM) { for (x = 0; xparent != NULL) { cil_log(CIL_INFO, "\n"); for (x = 0; xflavor != CIL_NODE) { cil_tree_print_node(current); } } cil_tree_print(current->cl_head, depth + 1); } if (current->next == NULL) { if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) { if (current->flavor == CIL_PERM) { cil_log(CIL_INFO, ")\n"); } else if (current->flavor != CIL_NODE) { for (x = 0; xparent != NULL) && (current->parent->parent == NULL)) cil_log(CIL_INFO, "\n\n"); } else { cil_tree_print(current->next, depth); } } else { cil_log(CIL_INFO, "Tree is NULL\n"); } } libsepol/cil/src/cil_tree.h0100644 0000000 0000000 00000006332 13756670065 014736 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_TREE_H_ #define CIL_TREE_H_ #include #include "cil_flavor.h" #include "cil_list.h" struct cil_tree { struct cil_tree_node *root; }; struct cil_tree_node { struct cil_tree_node *parent; struct cil_tree_node *cl_head; //Head of child_list struct cil_tree_node *cl_tail; //Tail of child_list struct cil_tree_node *next; //Each element in the list points to the next element enum cil_flavor flavor; uint32_t line; uint32_t hll_line; void *data; }; struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil); char *cil_tree_get_cil_path(struct cil_tree_node *node); __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...); int cil_tree_init(struct cil_tree **tree); void cil_tree_destroy(struct cil_tree **tree); void cil_tree_subtree_destroy(struct cil_tree_node *node); void cil_tree_children_destroy(struct cil_tree_node *node); void cil_tree_node_init(struct cil_tree_node **node); void cil_tree_node_destroy(struct cil_tree_node **node); void cil_tree_print(struct cil_tree_node *tree, uint32_t depth); //finished values #define CIL_TREE_SKIP_NOTHING 0 #define CIL_TREE_SKIP_NEXT 1 #define CIL_TREE_SKIP_HEAD 2 #define CIL_TREE_SKIP_ALL (CIL_TREE_SKIP_NOTHING | CIL_TREE_SKIP_NEXT | CIL_TREE_SKIP_HEAD) int cil_tree_walk(struct cil_tree_node *start_node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args); #endif /* CIL_TREE_H_ */ libsepol/cil/src/cil_verify.c0100644 0000000 0000000 00000115742 13756670065 015304 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_find.h" #include "cil_verify.h" int __cil_verify_name(const char *name) { int rc = SEPOL_ERR; int len; int i = 0; if (name == NULL) { cil_log(CIL_ERR, "Name is NULL\n"); goto exit; } len = strlen(name); if (len >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_ERR, "Name length greater than max name length of %d", CIL_MAX_NAME_LENGTH); rc = SEPOL_ERR; goto exit; } if (!isalpha(name[0])) { cil_log(CIL_ERR, "First character in %s is not a letter\n", name); goto exit; } for (i = 1; i < len; i++) { if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') { cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Invalid name\n"); return rc; } int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len) { int rc = SEPOL_ERR; int num_extras = 0; struct cil_tree_node *c = parse_current; int i = 0; while (i < len) { if ((s[i] & CIL_SYN_END) && c == NULL) { break; } if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) { if (c == NULL) { if (num_extras > 0) { i++; continue; } else { goto exit; } } else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) { c = c->next; num_extras++; continue; } else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) { c = c->next; num_extras++; continue; } } if (c == NULL) { goto exit; } if (s[i] & CIL_SYN_STRING) { if (c->data != NULL && c->cl_head == NULL) { c = c->next; i++; continue; } } if (s[i] & CIL_SYN_LIST) { if (c->data == NULL && c->cl_head != NULL) { c = c->next; i++; continue; } } if (s[i] & CIL_SYN_EMPTY_LIST) { if (c->data == NULL && c->cl_head == NULL) { c = c->next; i++; continue; } } goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Invalid syntax\n"); return rc; } int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor) { int rc; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); switch (op) { case CIL_NOT: syntax[2] = CIL_SYN_END; syntax_len = 3; break; case CIL_AND: case CIL_OR: case CIL_XOR: break; case CIL_EQ: case CIL_NEQ: if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) { cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data); goto exit; } break; case CIL_ALL: if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) { cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data); goto exit; } syntax[1] = CIL_SYN_END; syntax_len = 2; break; case CIL_RANGE: if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) { cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data); goto exit; } syntax[1] = CIL_SYN_STRING; syntax[2] = CIL_SYN_STRING; break; case CIL_NONE: /* String or List */ syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS; syntax[1] = CIL_SYN_END; syntax_len = 2; break; default: cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data); goto exit; } rc = __cil_verify_syntax(current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor) { if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) { if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) { cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n"); goto exit; } else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) { if (expr_flavor != CIL_MLSVALIDATETRANS) { cil_log(CIL_ERR, "u3, r3, and t3 can only be used with mlsvalidatetrans rules\n"); goto exit; } } } else { if (r_flavor == CIL_CONS_U2) { if (op != CIL_EQ && op != CIL_NEQ) { cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n"); goto exit; } else if (l_flavor != CIL_CONS_U1) { cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n"); goto exit; } } else if (r_flavor == CIL_CONS_R2) { if (l_flavor != CIL_CONS_R1) { cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n"); goto exit; } } else if (r_flavor == CIL_CONS_T2) { if (op != CIL_EQ && op != CIL_NEQ) { cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n"); goto exit; } else if (l_flavor != CIL_CONS_T1) { cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n"); goto exit; } } else if (r_flavor == CIL_CONS_L2) { if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) { cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n"); goto exit; } } else if (r_flavor == CIL_CONS_H2) { if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) { cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n"); goto exit; } } else if (r_flavor == CIL_CONS_H1) { if (l_flavor != CIL_CONS_L1) { cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n"); goto exit; } } } return SEPOL_OK; exit: return SEPOL_ERR; } int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op) { int rc; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_END, CIL_SYN_END, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); switch (op) { case CIL_NOT: syntax[1] = CIL_SYN_LIST; syntax_len--; break; case CIL_AND: case CIL_OR: syntax[1] = CIL_SYN_LIST; syntax[2] = CIL_SYN_LIST; break; case CIL_EQ: case CIL_NEQ: syntax[1] = CIL_SYN_STRING; syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST; break; case CIL_CONS_DOM: case CIL_CONS_DOMBY: case CIL_CONS_INCOMP: syntax[1] = CIL_SYN_STRING; syntax[2] = CIL_SYN_STRING; break; default: cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data); goto exit; } rc = __cil_verify_syntax(current, syntax, syntax_len); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Invalid constraint syntax\n"); goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list) { struct cil_list_item *i; cil_list_for_each(i, datum_list) { if (i->flavor == CIL_DATUM) { struct cil_symtab_datum *d = i->data; if (d == datum) { cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name); return SEPOL_ERR; } } else if (i->flavor == CIL_LIST) { int rc = cil_verify_no_self_reference(datum, i->data); if (rc != SEPOL_OK) { return SEPOL_ERR; } } } return SEPOL_OK; } int __cil_verify_ranges(struct cil_list *list) { int rc = SEPOL_ERR; struct cil_list_item *curr; struct cil_list_item *range = NULL; if (list == NULL || list->head == NULL) { goto exit; } cil_list_for_each(curr, list) { /* range */ if (curr->flavor == CIL_LIST) { range = ((struct cil_list*)curr->data)->head; if (range == NULL || range->next == NULL || range->next->next != NULL) { goto exit; } } } return SEPOL_OK; exit: cil_log(CIL_ERR,"Invalid Range syntax\n"); return rc; } struct cil_args_verify_order { uint32_t *flavor; }; int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) { struct cil_args_verify_order *args = extra_args; uint32_t *flavor = args->flavor; if (node->flavor == *flavor) { if (node->flavor == CIL_SID) { struct cil_sid *sid = node->data; if (sid->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_CLASS) { struct cil_class *class = node->data; if (class->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_CAT) { struct cil_cat *cat = node->data; if (cat->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_SENS) { struct cil_sens *sens = node->data; if (sens->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name); return SEPOL_ERR; } } } return SEPOL_OK; } int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor) { struct cil_args_verify_order extra_args; int rc = SEPOL_ERR; extra_args.flavor = &flavor; rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args); return rc; } int __cil_verify_initsids(struct cil_list *sids) { int rc = SEPOL_OK; struct cil_list_item *i; if (sids->head == NULL) { cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n"); return SEPOL_ERR; } cil_list_for_each(i, sids) { struct cil_sid *sid = i->data; if (sid->context == NULL) { struct cil_tree_node *node = sid->datum.nodes->head->data; cil_tree_log(node, CIL_ERR, "No context assigned to SID %s declared",sid->datum.name); rc = SEPOL_ERR; } } return rc; } int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats) { struct cil_list_item *i; cil_list_for_each(i, cats->datum_expr) { struct cil_cat *c = i->data; if (c == cat) { return CIL_TRUE; } } return CIL_FALSE; } int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats) { if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) { cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name); return SEPOL_ERR; } return SEPOL_OK; } int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats) { int rc = SEPOL_OK; struct cil_list_item *i, *j; if (!cats) { return SEPOL_OK; } if (!sens->cats_list) { cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name); return SEPOL_ERR; } cil_list_for_each(i, cats->datum_expr) { struct cil_cat *cat = i->data; int ok = CIL_FALSE; cil_list_for_each(j, sens->cats_list) { if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) { ok = CIL_TRUE; break; } } if (ok != CIL_TRUE) { cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n", cat->datum.name, sens->datum.name); rc = SEPOL_ERR; } } return rc; } int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high) { struct cil_list_item *curr; int found = CIL_FALSE; int rc = SEPOL_ERR; cil_list_for_each(curr, db->sensitivityorder) { if (curr->data == low) { found = CIL_TRUE; } if ((found == CIL_TRUE) && (curr->data == high)) { break; } } if (found != CIL_TRUE || curr == NULL) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n", high->datum.name, low->datum.name); return rc; } int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high) { int rc = SEPOL_ERR; struct cil_list_item *item; if (low == NULL || (low == NULL && high == NULL)) { return SEPOL_OK; } if (high == NULL) { rc = SEPOL_ERR; goto exit; } cil_list_for_each(item, low->datum_expr) { rc = __cil_verify_cat_in_cats(item->data, high); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n"); return rc; } int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr) { int rc = SEPOL_ERR; rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n"); goto exit; } rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n"); goto exit; } return SEPOL_OK; exit: return rc; } int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_levelrange *lr = node->data; rc = __cil_verify_levelrange(db, lr); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid named range"); return rc; } static int __cil_verify_user_pre_eval(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_user *user = node->data; if (user->dftlevel == NULL) { cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name); goto exit; } else if (user->range == NULL) { cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name); goto exit; } else if (user->bounds != NULL) { int steps = 0; int limit = 2; struct cil_user *u1 = user; struct cil_user *u2 = user->bounds; while (u2 != NULL) { if (u1 == u2) { cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; u1 = u2; } u2 = u2->bounds; steps++; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid user"); return rc; } static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_user *user = node->data; /* Verify user range only if anonymous */ if (user->range->datum.name == NULL) { rc = __cil_verify_levelrange(db, user->range); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid user"); return rc; } int __cil_verify_role(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_role *role = node->data; int steps = 0; int limit = 2; struct cil_role *r1 = role; struct cil_role *r2 = role->bounds; while (r2 != NULL) { if (r1 == r2) { cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; r1 = r2; } r2 = r2->bounds; steps++; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid role"); return rc; } int __cil_verify_type(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_type *type = node->data; int steps = 0; int limit = 2; struct cil_type *t1 = type; struct cil_type *t2 = type->bounds; while (t2 != NULL) { if (t1 == t2) { cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; t1 = t2; } t2 = t2->bounds; steps++; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid type"); return rc; } int __cil_verify_context(struct cil_db *db, struct cil_context *ctx) { int rc = SEPOL_ERR; struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; struct cil_level *user_low = user->range->low; struct cil_level *user_high = user->range->high; struct cil_level *ctx_low = ctx->range->low; struct cil_level *ctx_high = ctx->range->high; struct cil_list *sensitivityorder = db->sensitivityorder; struct cil_list_item *curr; int found = CIL_FALSE; if (user->roles != NULL) { if (!ebitmap_get_bit(user->roles, role->value)) { cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str); rc = SEPOL_ERR; goto exit; } if (role->types != NULL) { if (!ebitmap_get_bit(role->types, type->value)) { cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str); rc = SEPOL_ERR; goto exit; } /* Verify range only when anonymous */ if (ctx->range->datum.name == NULL) { rc = __cil_verify_levelrange(db, ctx->range); if (rc != SEPOL_OK) { goto exit; } } for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) { struct cil_sens *sens = curr->data; if (found == CIL_FALSE) { if (sens == user_low->sens) { found = CIL_TRUE; } else if (sens == ctx_low->sens) { cil_log(CIL_ERR, "Range %s is invalid for user %s\n", ctx->range_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } if (found == CIL_TRUE) { if (sens == ctx_high->sens) { break; } else if (sens == user_high->sens) { cil_log(CIL_ERR, "Range %s is invalid for user %s\n", ctx->range_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Invalid context\n"); return rc; } int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_context *ctx = node->data; rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid named context"); return rc; } int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab) { int rc = SEPOL_ERR; struct cil_type_rule *typerule = NULL; struct cil_roletransition *roletrans = NULL; struct cil_complex_symtab_key ckey; switch (node->flavor) { case CIL_ROLETRANSITION: { roletrans = node->data; ckey.key1 = (intptr_t)roletrans->src; ckey.key2 = (intptr_t)roletrans->tgt; ckey.key3 = (intptr_t)roletrans->obj; ckey.key4 = CIL_ROLETRANSITION; break; } case CIL_TYPE_RULE: { typerule = node->data; ckey.key1 = (intptr_t)typerule->src; ckey.key2 = (intptr_t)typerule->tgt; ckey.key3 = (intptr_t)typerule->obj; ckey.key4 = (intptr_t)typerule->rule_kind; break; } default: break; } rc = cil_complex_symtab_insert(symtab, &ckey, NULL); if (rc == SEPOL_EEXIST) { struct cil_complex_symtab_datum *datum = NULL; cil_complex_symtab_search(symtab, &ckey, &datum); if (datum == NULL) { cil_tree_log(node, CIL_ERR, "Duplicate rule defined"); rc = SEPOL_ERR; goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid rule"); return rc; } int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args) { int rc = SEPOL_ERR; struct cil_tree_node *rule_node = node; struct cil_booleanif *bif = node->parent->parent->data; switch (rule_node->flavor) { case CIL_AVRULE: { struct cil_avrule *avrule = NULL; avrule = rule_node->data; if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) { if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)"); } else { cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block"); } rc = SEPOL_ERR; goto exit; } break; } case CIL_TYPE_RULE: /* struct cil_type_rule *typerule = NULL; struct cil_tree_node *temp_node = NULL; struct cil_complex_symtab *symtab = extra_args; struct cil_complex_symtab_key ckey; struct cil_complex_symtab_datum datum; typerule = rule_node->data; ckey.key1 = (intptr_t)typerule->src; ckey.key2 = (intptr_t)typerule->tgt; ckey.key3 = (intptr_t)typerule->obj; ckey.key4 = (intptr_t)typerule->rule_kind; datum.data = node; rc = cil_complex_symtab_insert(symtab, &ckey, &datum); if (rc != SEPOL_OK) { goto exit; } for (temp_node = rule_node->next; temp_node != NULL; temp_node = temp_node->next) { if (temp_node->flavor == CIL_TYPE_RULE) { typerule = temp_node->data; if ((intptr_t)typerule->src == ckey.key1 && (intptr_t)typerule->tgt == ckey.key2 && (intptr_t)typerule->obj == ckey.key3 && (intptr_t)typerule->rule_kind == ckey.key4) { cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line); rc = SEPOL_ERR; goto exit; } } } break;*/ //TODO Fix duplicate type_rule detection break; case CIL_CALL: //Fall through to check content of call break; case CIL_TUNABLEIF: //Fall through break; case CIL_NAMETYPETRANSITION: /* While type transitions with file component are not allowed in booleanif statements if they don't have "*" as the file. We can't check that here. Or at least we won't right now. */ break; default: { const char * flavor = cil_node_to_string(node); if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor); } else { cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor); } goto exit; } } rc = SEPOL_OK; exit: return rc; } int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab) { int rc = SEPOL_ERR; struct cil_booleanif *bif = (struct cil_booleanif*)node->data; struct cil_tree_node *cond_block = node->cl_head; while (cond_block != NULL) { rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab); if (rc != SEPOL_OK) { goto exit; } cond_block = cond_block->next; } return SEPOL_OK; exit: if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)"); } else { cil_tree_log(node, CIL_ERR, "Invalid booleanif"); } return rc; } int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_netifcon *netif = node->data; struct cil_context *if_ctx = netif->if_context; struct cil_context *pkt_ctx = netif->packet_context; /* Verify only when anonymous */ if (if_ctx->datum.name == NULL) { rc = __cil_verify_context(db, if_ctx); if (rc != SEPOL_OK) { goto exit; } } /* Verify only when anonymous */ if (pkt_ctx->datum.name == NULL) { rc = __cil_verify_context(db, pkt_ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid netifcon"); return rc; } int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ibendportcon *ib_end_port = node->data; struct cil_context *ctx = ib_end_port->context; /* Verify only when anonymous */ if (!ctx->datum.name) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ibendportcon"); return rc; } int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_genfscon *genfs = node->data; struct cil_context *ctx = genfs->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid genfscon"); return rc; } int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_filecon *file = node->data; struct cil_context *ctx = file->context; if (ctx == NULL) { rc = SEPOL_OK; goto exit; } /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Invalid filecon"); goto exit; } } return SEPOL_OK; exit: return rc; } int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_nodecon *nodecon = node->data; struct cil_context *ctx = nodecon->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid nodecon"); return rc; } int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ibpkeycon *pkey = node->data; struct cil_context *ctx = pkey->context; /* Verify only when anonymous */ if (!ctx->datum.name) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon"); return rc; } int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_portcon *port = node->data; struct cil_context *ctx = port->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid portcon"); return rc; } int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_pirqcon *pirq = node->data; struct cil_context *ctx = pirq->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid pirqcon"); return rc; } int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_iomemcon *iomem = node->data; struct cil_context *ctx = iomem->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid iomemcon"); return rc; } int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ioportcon *ioport = node->data; struct cil_context *ctx = ioport->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ioportcon"); return rc; } int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_pcidevicecon *pcidev = node->data; struct cil_context *ctx = pcidev->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon"); return rc; } int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_devicetreecon *dt = node->data; struct cil_context *ctx = dt->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid devicetreecon"); return rc; } int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_fsuse *fsuse = node->data; struct cil_context *ctx = fsuse->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid fsuse"); return rc; } int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node) { int rc; struct cil_list *classes = NULL; struct cil_list_item *item; struct cil_class *class; struct cil_symtab_datum *perm_datum; char *kind_str; switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: kind_str = CIL_KEY_IOCTL; break; default: cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind); rc = SEPOL_ERR; goto exit; } classes = cil_expand_class(permx->obj); cil_list_for_each(item, classes) { class = item->data; rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum); if (rc == SEPOL_ENOENT) { if (class->common != NULL) { rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum); } if (rc == SEPOL_ENOENT) { cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name); rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: if (classes != NULL) { cil_list_destroy(&classes, CIL_FALSE); } return rc; } int __cil_verify_avrulex(struct cil_tree_node *node) { struct cil_avrule *avrulex = node->data; return __cil_verify_permissionx(avrulex->perms.x.permx, node); } int __cil_verify_class(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_class *class = node->data; if (class->common != NULL) { struct cil_class *common = class->common; struct cil_tree_node *common_node = common->datum.nodes->head->data; struct cil_tree_node *curr_com_perm = NULL; for (curr_com_perm = common_node->cl_head; curr_com_perm != NULL; curr_com_perm = curr_com_perm->next) { struct cil_perm *com_perm = curr_com_perm->data; struct cil_tree_node *curr_class_perm = NULL; for (curr_class_perm = node->cl_head; curr_class_perm != NULL; curr_class_perm = curr_class_perm->next) { struct cil_perm *class_perm = curr_class_perm->data; if (com_perm->datum.name == class_perm->datum.name) { cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name); goto exit; } } } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid class"); return rc; } int __cil_verify_policycap(struct cil_tree_node *node) { int rc; struct cil_policycap *polcap = node->data; rc = sepol_polcap_getnum((const char*)polcap->datum.name); if (rc == SEPOL_ERR) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name); return rc; } int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; int *avrule_cnt = 0; int *handleunknown; int *mls; int *nseuserdflt = 0; int *pass = 0; struct cil_args_verify *args = extra_args; struct cil_complex_symtab *csymtab = NULL; struct cil_db *db = NULL; if (node == NULL || extra_args == NULL) { goto exit; } db = args->db; avrule_cnt = args->avrule_cnt; handleunknown = args->handleunknown; mls = args->mls; nseuserdflt = args->nseuserdflt; csymtab = args->csymtab; pass = args->pass; if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } else if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } rc = SEPOL_OK; goto exit; } switch (*pass) { case 0: { switch (node->flavor) { case CIL_USER: rc = __cil_verify_user_post_eval(db, node); break; case CIL_SELINUXUSERDEFAULT: (*nseuserdflt)++; rc = SEPOL_OK; break; case CIL_ROLE: rc = __cil_verify_role(node); break; case CIL_TYPE: rc = __cil_verify_type(node); break; case CIL_AVRULE: (*avrule_cnt)++; rc = SEPOL_OK; break; case CIL_HANDLEUNKNOWN: if (*handleunknown != -1) { cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n"); rc = SEPOL_ERR; } else { *handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown; rc = SEPOL_OK; } break; case CIL_MLS: if (*mls != -1) { cil_log(CIL_ERR, "Policy can not have more than one mls\n"); rc = SEPOL_ERR; } else { *mls = ((struct cil_mls*)node->data)->value; rc = SEPOL_OK; } break; case CIL_ROLETRANSITION: rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right //rc = __cil_verify_rule(node, csymtab); break; case CIL_TYPE_RULE: rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right //rc = __cil_verify_rule(node, csymtab); break; case CIL_BOOLEANIF: rc = __cil_verify_booleanif(node, csymtab); *finished = CIL_TREE_SKIP_HEAD; break; case CIL_LEVELRANGE: rc = __cil_verify_named_levelrange(db, node); break; case CIL_CLASS: rc = __cil_verify_class(node); break; case CIL_POLICYCAP: rc = __cil_verify_policycap(node); break; default: rc = SEPOL_OK; break; } break; } case 1: { switch (node->flavor) { case CIL_CONTEXT: rc = __cil_verify_named_context(db, node); break; case CIL_NETIFCON: rc = __cil_verify_netifcon(db, node); break; case CIL_GENFSCON: rc = __cil_verify_genfscon(db, node); break; case CIL_FILECON: rc = __cil_verify_filecon(db, node); break; case CIL_NODECON: rc = __cil_verify_nodecon(db, node); break; case CIL_IBPKEYCON: rc = __cil_verify_ibpkeycon(db, node); break; case CIL_IBENDPORTCON: rc = __cil_verify_ibendportcon(db, node); break; case CIL_PORTCON: rc = __cil_verify_portcon(db, node); break; case CIL_PIRQCON: rc = __cil_verify_pirqcon(db, node); break; case CIL_IOMEMCON: rc = __cil_verify_iomemcon(db, node); break; case CIL_IOPORTCON: rc = __cil_verify_ioportcon(db, node); break; case CIL_PCIDEVICECON: rc = __cil_verify_pcidevicecon(db, node); break; case CIL_DEVICETREECON: rc = __cil_verify_devicetreecon(db, node); break; case CIL_FSUSE: rc = __cil_verify_fsuse(db, node); break; case CIL_AVRULEX: rc = __cil_verify_avrulex(node); break; case CIL_PERMISSIONX: rc = __cil_verify_permissionx(node->data, node); break; case CIL_RANGETRANSITION: rc = SEPOL_OK; break; default: rc = SEPOL_OK; break; } break; } default: rc = SEPOL_ERR; } exit: return rc; } static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { return SEPOL_OK; } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; if (&cmp->datum == orig) { rc = SEPOL_ERR; goto exit; } rc = __cil_verify_classperms(cmp->classperms, orig); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; if (&cp->datum == orig) { rc = SEPOL_ERR; goto exit; } rc = __cil_verify_classperms(cp->classperms, orig); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int __cil_verify_classpermission(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_classpermission *cp = node->data; if (cp->classperms == NULL) { cil_tree_log(node, CIL_ERR, "Classpermission %s does not have a classpermissionset", cp->datum.name); rc = SEPOL_ERR; goto exit; } rc = __cil_verify_classperms(cp->classperms, &cp->datum); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Found circular class permissions involving the set %s",cp->datum.name); goto exit; } rc = SEPOL_OK; exit: return rc; } struct cil_verify_map_args { struct cil_class *class; struct cil_tree_node *node; int rc; }; static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { int rc = SEPOL_ERR; struct cil_verify_map_args *map_args = args; struct cil_perm *cmp = (struct cil_perm *)d; if (cmp->classperms == NULL) { cil_tree_log(map_args->node, CIL_ERR, "Map class %s does not have a classmapping for %s", map_args->class->datum.name, cmp->datum.name); map_args->rc = SEPOL_ERR; goto exit; } rc = __cil_verify_classperms(cmp->classperms, &cmp->datum); if (rc != SEPOL_OK) { cil_tree_log(map_args->node, CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", map_args->class->datum.name, cmp->datum.name); map_args->rc = SEPOL_ERR; goto exit; } exit: return SEPOL_OK; } static int __cil_verify_map_class(struct cil_tree_node *node) { struct cil_class *mc = node->data; struct cil_verify_map_args map_args; map_args.class = mc; map_args.node = node; map_args.rc = SEPOL_OK; cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args); if (map_args.rc != SEPOL_OK) { return SEPOL_ERR; } return SEPOL_OK; } int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) { int rc = SEPOL_ERR; if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } else if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } rc = SEPOL_OK; goto exit; } switch (node->flavor) { case CIL_USER: rc = __cil_verify_user_pre_eval(node); if (rc != SEPOL_OK) { goto exit; } break; case CIL_MAP_CLASS: rc = __cil_verify_map_class(node); break; case CIL_CLASSPERMISSION: rc = __cil_verify_classpermission(node); break; default: rc = SEPOL_OK; break; } exit: return rc; } libsepol/cil/src/cil_verify.h0100644 0000000 0000000 00000006361 13756670065 015305 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_VERIFY_H_ #define CIL_VERIFY_H_ #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_tree.h" #include "cil_list.h" enum cil_syntax { CIL_SYN_STRING = 1 << 0, CIL_SYN_LIST = 1 << 1, CIL_SYN_EMPTY_LIST = 1 << 2, CIL_SYN_N_LISTS = 1 << 3, CIL_SYN_N_STRINGS = 1 << 4, CIL_SYN_END = 1 << 5 }; struct cil_args_verify { struct cil_db *db; struct cil_complex_symtab *csymtab; int *avrule_cnt; int *handleunknown; int *mls; int *nseuserdflt; int *pass; }; int __cil_verify_name(const char *name); int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len); int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor); int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor); int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op); int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list); int __cil_verify_ranges(struct cil_list *list); int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor); int __cil_verify_initsids(struct cil_list *sids); int __cil_verify_senscat(struct cil_sens *sens, struct cil_cat *cat); int __cil_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args); int __cil_pre_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args); #endif libsepol/cil/src/cil_write_ast.c0100644 0000000 0000000 00000113374 13756670065 016000 0ustar000000000 0000000 #include #include "cil_flavor.h" #include "cil_internal.h" #include "cil_log.h" #include "cil_tree.h" struct cil_args_write { FILE *cil_out; struct cil_db *db; }; static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren); static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren); static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args); static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args); static int __cil_strlist_concat(struct cil_list *str_list, char **out_str, int paren) { size_t len = paren ? 3 : 1; size_t num_elems = 0; char *p = NULL; struct cil_list_item *curr; /* get buffer size */ cil_list_for_each(curr, str_list) { len += strlen((char *)curr->data); num_elems++; } if (num_elems != 0) { /* add spaces between elements */ len += num_elems - 1; } *out_str = cil_malloc(len); p = *out_str; if (paren) *p++ = '('; cil_list_for_each(curr, str_list) { size_t src_len = strlen((char *)curr->data); memcpy(p, curr->data, src_len); p += src_len; if (curr->next != NULL) *p++ = ' '; } if (paren) *p++ = ')'; *p++ = '\0'; return SEPOL_OK; } static int __cil_unfill_expr_helper(struct cil_list_item *curr, struct cil_list_item **next, char **out_str, int paren) { int rc = SEPOL_ERR; char *str = NULL; char *operand1 = NULL; char *operand2 = NULL; switch(curr->flavor) { case CIL_LIST: rc = cil_unfill_expr((struct cil_list *)curr->data, &str, paren); if (rc != SEPOL_OK) goto exit; *out_str = str; *next = curr->next; break; case CIL_STRING: str = strdup((char *)curr->data); if (!str) { cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); rc = SEPOL_ERR; goto exit; } *out_str = str; *next = curr->next; break; case CIL_DATUM: str = strdup(((struct cil_symtab_datum *)curr->data)->name); if (!str) { cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); rc = SEPOL_ERR; goto exit; } *out_str = str; *next = curr->next; break; case CIL_OP: { char *op_str = NULL; size_t len = 0; enum cil_flavor op_flavor = (enum cil_flavor)curr->data; switch (op_flavor) { case CIL_AND: op_str = CIL_KEY_AND; break; case CIL_OR: op_str = CIL_KEY_OR; break; case CIL_NOT: op_str = CIL_KEY_NOT; break; case CIL_ALL: op_str = CIL_KEY_ALL; break; case CIL_EQ: op_str = CIL_KEY_EQ; break; case CIL_NEQ: op_str = CIL_KEY_NEQ; break; case CIL_RANGE: op_str = CIL_KEY_RANGE; break; case CIL_XOR: op_str = CIL_KEY_XOR; break; case CIL_CONS_DOM: op_str = CIL_KEY_CONS_DOM; break; case CIL_CONS_DOMBY: op_str = CIL_KEY_CONS_DOMBY; break; case CIL_CONS_INCOMP: op_str = CIL_KEY_CONS_INCOMP; break; default: cil_log(CIL_ERR, "Unknown operator in expression: %d\n", op_flavor); goto exit; break; } /* all operands take two args except for 'all' and 'not', which take * one and two, respectively */ len = strlen(op_str) + 3; if (op_flavor == CIL_ALL) { *out_str = cil_malloc(len); sprintf(*out_str, "(%s)", op_str); *next = curr->next; } else if (op_flavor == CIL_NOT) { rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren); if (rc != SEPOL_OK) goto exit; len += strlen(operand1) + 1; *out_str = cil_malloc(len); sprintf(*out_str, "(%s %s)", op_str, operand1); // *next already set by recursive call } else { rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren); if (rc != SEPOL_OK) goto exit; len += strlen(operand1) + 1; // *next contains operand2, but keep track of next after that rc = __cil_unfill_expr_helper(*next, next, &operand2, paren); if (rc != SEPOL_OK) goto exit; len += strlen(operand2) + 1; *out_str = cil_malloc(len); sprintf(*out_str, "(%s %s %s)", op_str, operand1, operand2); // *next already set by recursive call } } break; case CIL_CONS_OPERAND: { enum cil_flavor operand_flavor = (enum cil_flavor)curr->data; char *operand_str = NULL; switch (operand_flavor) { case CIL_CONS_U1: operand_str = CIL_KEY_CONS_U1; break; case CIL_CONS_U2: operand_str = CIL_KEY_CONS_U2; break; case CIL_CONS_U3: operand_str = CIL_KEY_CONS_U3; break; case CIL_CONS_T1: operand_str = CIL_KEY_CONS_T1; break; case CIL_CONS_T2: operand_str = CIL_KEY_CONS_T2; break; case CIL_CONS_T3: operand_str = CIL_KEY_CONS_T3; break; case CIL_CONS_R1: operand_str = CIL_KEY_CONS_R1; break; case CIL_CONS_R2: operand_str = CIL_KEY_CONS_R2; break; case CIL_CONS_R3: operand_str = CIL_KEY_CONS_R3; break; case CIL_CONS_L1: operand_str = CIL_KEY_CONS_L1; break; case CIL_CONS_L2: operand_str = CIL_KEY_CONS_L2; break; case CIL_CONS_H1: operand_str = CIL_KEY_CONS_H1; break; case CIL_CONS_H2: operand_str = CIL_KEY_CONS_H2; break; default: cil_log(CIL_ERR, "Unknown operand in expression\n"); goto exit; break; } str = strdup(operand_str); if (!str) { cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); rc = SEPOL_ERR; goto exit; } *out_str = str; *next = curr->next; } break; default: cil_log(CIL_ERR, "Unknown flavor in expression\n"); goto exit; break; } rc = SEPOL_OK; exit: free(operand1); free(operand2); return rc; } static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren) { int rc = SEPOL_ERR; /* reuse cil_list to keep track of strings */ struct cil_list *str_list = NULL; struct cil_list_item *curr = NULL; cil_list_init(&str_list, CIL_NONE); /* iterate through cil_list, grabbing elements as needed */ curr = expr_str->head; while(curr != NULL) { char *str = NULL; struct cil_list_item *next = NULL; rc = __cil_unfill_expr_helper(curr, &next, &str, paren); if (rc != SEPOL_OK) goto exit; cil_list_append(str_list, CIL_STRING, (void *) str); str = NULL; curr = next; } rc = __cil_strlist_concat(str_list, out_str, paren); if (rc != SEPOL_OK) goto exit; rc = SEPOL_OK; exit: cil_list_for_each(curr, str_list) { free(curr->data); } cil_list_destroy(&str_list, 0); return rc; } static int cil_unfill_cats(struct cil_cats *cats, char **out_str) { return cil_unfill_expr(cats->str_expr, out_str, 0); } static int cil_unfill_level(struct cil_level *lvl, char **out_str) { int rc = SEPOL_ERR; size_t len = 0; char *sens, *cats = NULL; sens = lvl->sens_str; len = strlen(sens) + 3; // '()\0' if (lvl->cats != NULL) { rc = cil_unfill_cats(lvl->cats, &cats); if (rc != SEPOL_OK) goto exit; len += strlen(cats) + 1; } *out_str = cil_malloc(len); if (cats == NULL) { if (sprintf(*out_str, "(%s)", sens) < 0) { cil_log(CIL_ERR, "Error unpacking and writing level\n"); rc = SEPOL_ERR; goto exit; } } else { if (sprintf(*out_str, "(%s %s)", sens, cats) < 0) { cil_log(CIL_ERR, "Error unpacking and writing level\n"); rc = SEPOL_ERR; goto exit; } } rc = SEPOL_OK; exit: free(cats); return rc; } static int cil_unfill_levelrange(struct cil_levelrange *lvlrnge, char **out_str) { int rc = SEPOL_ERR; size_t len = 0; char *low = NULL, *high = NULL; if (lvlrnge->low_str != NULL) { low = strdup(lvlrnge->low_str); if (low == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_level(lvlrnge->low, &low); if (rc != SEPOL_OK) goto exit; } if (lvlrnge->high_str != NULL) { high = strdup(lvlrnge->high_str); if (high == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_level(lvlrnge->high, &high); if (rc != SEPOL_OK) goto exit; } len = strlen(low) + strlen(high) + 4; *out_str = cil_malloc(len); if (sprintf(*out_str, "(%s %s)", low, high) < 0) { cil_log(CIL_ERR, "Error unpacking and writing levelrange\n"); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: free(low); free(high); return rc; } static int cil_unfill_context(struct cil_context *context, char **out_str) { int rc = SEPOL_ERR; size_t len = 0; char *user_str, *role_str, *type_str; char *range_str = NULL; user_str = context->user_str; role_str = context->role_str; type_str = context->type_str; if (context->range_str != NULL) { range_str = strdup(context->range_str); if (range_str == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy range string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_levelrange(context->range, &range_str); if (rc != SEPOL_OK) goto exit; } len = strlen(user_str) + strlen(role_str) + strlen(type_str) + strlen(range_str) + 6; *out_str = cil_malloc(len); if (sprintf(*out_str, "(%s %s %s %s)", user_str, role_str, type_str, range_str) < 0) { cil_log(CIL_ERR, "Error unpacking and writing context\n"); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: free(range_str); return rc; } static int cil_unfill_permx(struct cil_permissionx *permx, char **out_str) { size_t len = 3; int rc = SEPOL_ERR; char *kind, *obj; char *expr = NULL; switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: kind = CIL_KEY_IOCTL; break; default: cil_log(CIL_ERR, "Unknown permissionx kind: %d\n", permx->kind); rc = SEPOL_ERR; goto exit; break; } obj = permx->obj_str; rc = cil_unfill_expr(permx->expr_str, &expr, 1); if (rc != SEPOL_OK) goto exit; len += strlen(kind) + strlen(obj) + strlen(expr) + 2; *out_str = cil_malloc(len); if (sprintf(*out_str, "(%s %s %s)", kind, obj, expr) < 0) { cil_log(CIL_ERR, "Error writing xperm\n"); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: free(expr); return rc; } #define cil_write_unsupported(flavor) _cil_write_unsupported(flavor, __LINE__) static int _cil_write_unsupported(const char *flavor, int line) { cil_log(CIL_ERR, "flavor \"%s\" is not supported, look in file \"%s\"" " on line %d to add support.\n", flavor, __FILE__, line); return SEPOL_ENOTSUP; } static int cil_write_policycap(struct cil_tree_node *node, FILE *cil_out) { struct cil_policycap *polcap = (struct cil_policycap *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_POLICYCAP, polcap->datum.name); return SEPOL_OK; } static int cil_write_perm(struct cil_tree_node *node, FILE *cil_out) { struct cil_perm *perm = (struct cil_perm *)node->data; fprintf(cil_out, "%s", perm->datum.name); if (node->next != NULL) fprintf(cil_out, " "); return SEPOL_OK; } static int cil_write_class(struct cil_tree_node *node, uint32_t *finished, struct cil_args_write *extra_args) { int rc = SEPOL_ERR; FILE *cil_out = extra_args->cil_out; struct cil_symtab_datum *datum = (struct cil_symtab_datum *)node->data; char *class_type = (node->flavor == CIL_CLASS) ? CIL_KEY_CLASS : CIL_KEY_COMMON; /* print preamble */ fprintf(cil_out, "(%s %s ", class_type, datum->name); if (node->cl_head == NULL) { /* no associated perms in this part of tree */ fprintf(cil_out, "()"); } else { /* visit subtree (perms) */ rc = cil_tree_walk(node, __cil_write_node_helper, __cil_write_first_child_helper, __cil_write_last_child_helper, extra_args); if (rc != SEPOL_OK) goto exit; } /* postamble (trailing paren) */ fprintf(cil_out, ")\n"); *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; exit: return rc; } static int cil_write_classorder(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *ord_str = NULL; struct cil_classorder *classord = (struct cil_classorder *)node->data; /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ rc = cil_unfill_expr(classord->class_list_str, &ord_str, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s)\n", CIL_KEY_CLASSORDER, ord_str); rc = SEPOL_OK; exit: free(ord_str); return rc; } static int cil_write_classcommon(struct cil_tree_node *node, FILE *cil_out) { struct cil_classcommon *classcommon = (struct cil_classcommon *)node->data; fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_CLASSCOMMON, classcommon->class_str, classcommon->common_str); return SEPOL_OK; } static int cil_write_sid(struct cil_tree_node *node, FILE *cil_out) { struct cil_sid *sid = (struct cil_sid *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_SID, sid->datum.name); return SEPOL_OK; } static int cil_write_sidcontext(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *sid; char *ctx_str = NULL; struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data; sid = sidcon->sid_str; if (sidcon->context_str != NULL) { ctx_str = strdup(sidcon->context_str); if (ctx_str == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_context(sidcon->context, &ctx_str); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_SIDCONTEXT, sid, ctx_str); rc = SEPOL_OK; exit: free(ctx_str); return rc; } static int cil_write_sidorder(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *ord_str = NULL; struct cil_sidorder *sidord = (struct cil_sidorder *)node->data; /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ rc = cil_unfill_expr(sidord->sid_list_str, &ord_str, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s)\n", CIL_KEY_SIDORDER, ord_str); rc = SEPOL_OK; exit: free(ord_str); return rc; } static int cil_write_user(struct cil_tree_node *node, FILE *cil_out) { struct cil_user *user = (struct cil_user *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_USER, user->datum.name); return SEPOL_OK; } static int cil_write_userrole(struct cil_tree_node *node, FILE *cil_out) { struct cil_userrole *userrole = (struct cil_userrole *)node->data; fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERROLE, userrole->user_str, userrole->role_str); return SEPOL_OK; } static int cil_write_userlevel(struct cil_tree_node *node, FILE *cil_out) { struct cil_userlevel *usrlvl = (struct cil_userlevel *)node->data; int rc = SEPOL_ERR; char *usr; char *lvl = NULL; usr = usrlvl->user_str; if (usrlvl->level_str != NULL) { lvl = strdup(usrlvl->level_str); if (lvl == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_level(usrlvl->level, &lvl); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERLEVEL, usr, lvl); rc = SEPOL_OK; exit: free(lvl); return rc; } static int cil_write_userrange(struct cil_tree_node *node, FILE *cil_out) { struct cil_userrange *usrrng = (struct cil_userrange *)node->data; int rc = SEPOL_ERR; char *usr; char *range = NULL; usr = usrrng->user_str; if (usrrng->range_str != NULL) { range = strdup(usrrng->range_str); if (range == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy levelrange string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_levelrange(usrrng->range, &range); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERRANGE, usr, range); rc = SEPOL_OK; exit: free(range); return rc; } static int cil_write_role(struct cil_tree_node *node, FILE *cil_out) { struct cil_role *role = (struct cil_role *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLE, role->datum.name); return SEPOL_OK; } static int cil_write_roletype(struct cil_tree_node *node, FILE *cil_out) { struct cil_roletype *roletype = (struct cil_roletype *)node->data; fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_ROLETYPE, roletype->role_str, roletype->type_str); return SEPOL_OK; } static int cil_write_roleattribute(struct cil_tree_node *node, FILE *cil_out) { struct cil_roleattribute *roleattr = (struct cil_roleattribute *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLEATTRIBUTE, roleattr->datum.name); return SEPOL_OK; } static int cil_write_type(struct cil_tree_node *node, FILE *cil_out) { struct cil_type *type = (struct cil_type *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPE, type->datum.name); return SEPOL_OK; } static int cil_write_typepermissive(struct cil_tree_node *node, FILE *cil_out) { struct cil_typepermissive *type = (struct cil_typepermissive *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEPERMISSIVE, type->type_str); return SEPOL_OK; } static int cil_write_typeattribute(struct cil_tree_node *node, FILE *cil_out) { struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEATTRIBUTE, typeattr->datum.name); return SEPOL_OK; } static int cil_write_typeattributeset(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *typeattr; char *set_str = NULL; struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *)node->data; typeattr = typeattrset->attr_str; rc = cil_unfill_expr(typeattrset->str_expr, &set_str, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_TYPEATTRIBUTESET, typeattr, set_str); rc = SEPOL_OK; exit: free(set_str); return rc; } static int cil_write_expandtypeattribute(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *attr_strs = NULL; struct cil_expandtypeattribute *expandattr = (struct cil_expandtypeattribute *)node->data; rc = cil_unfill_expr(expandattr->attr_strs, &attr_strs, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_EXPANDTYPEATTRIBUTE, attr_strs, expandattr->expand ? CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE); rc = SEPOL_OK; exit: free(attr_strs); return rc; } static int cil_write_alias(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *type; struct cil_alias *alias = (struct cil_alias *)node->data; switch (node->flavor) { case CIL_TYPEALIAS: type = CIL_KEY_TYPEALIAS; break; case CIL_SENSALIAS: type = CIL_KEY_SENSALIAS; break; case CIL_CATALIAS: type = CIL_KEY_CATALIAS; break; default: cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor); rc = SEPOL_ERR; goto exit; break; } fprintf(cil_out, "(%s %s)\n", type, alias->datum.name); rc = SEPOL_OK; exit: return rc; } static int cil_write_aliasactual(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *type, *alias, *actual; struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data; switch (node->flavor) { case CIL_TYPEALIASACTUAL: type = CIL_KEY_TYPEALIASACTUAL; break; case CIL_SENSALIASACTUAL: type = CIL_KEY_SENSALIASACTUAL; break; case CIL_CATALIASACTUAL: type = CIL_KEY_CATALIASACTUAL; break; default: cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor); rc = SEPOL_ERR; goto exit; break; } alias = aliasact->alias_str; actual = aliasact->actual_str; fprintf(cil_out, "(%s %s %s)\n", type, alias, actual); rc = SEPOL_OK; exit: return rc; } static int cil_write_nametypetransition(struct cil_tree_node *node, FILE *cil_out) { char *src, *tgt, *obj, *res, *name; struct cil_nametypetransition *ntrans = (struct cil_nametypetransition *)node->data; src = ntrans->src_str; tgt = ntrans->tgt_str; obj = ntrans->obj_str; res = ntrans->result_str; name = ntrans->name_str; fprintf(cil_out, "(%s %s %s %s \"%s\" %s)\n", CIL_KEY_TYPETRANSITION, src, tgt, obj, name, res); return SEPOL_OK; } static int cil_write_avrule_x(struct cil_avrule *avrule, FILE *cil_out) { int rc = SEPOL_ERR; char *rulekind, *src, *tgt; char *xperms = NULL; switch (avrule->rule_kind) { case CIL_AVRULE_ALLOWED: rulekind = CIL_KEY_ALLOWX; break; case CIL_AVRULE_AUDITALLOW: rulekind = CIL_KEY_AUDITALLOWX; break; case CIL_AVRULE_DONTAUDIT: rulekind = CIL_KEY_DONTAUDITX; break; case CIL_AVRULE_NEVERALLOW: rulekind = CIL_KEY_NEVERALLOWX; break; default: cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind); rc = SEPOL_ERR; goto exit; break; } src = avrule->src_str; tgt = avrule->tgt_str; if (avrule->perms.x.permx_str != NULL) { xperms = strdup(avrule->perms.x.permx_str); if (xperms == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy xperms string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_permx(avrule->perms.x.permx, &xperms); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, xperms); rc = SEPOL_OK; exit: free(xperms); return rc; } static int cil_write_avrule_orig(struct cil_avrule *avrule, FILE *cil_out) { int rc = SEPOL_ERR; char *rulekind, *src, *tgt; char *classperms = NULL; switch (avrule->rule_kind) { case CIL_AVRULE_ALLOWED: rulekind = CIL_KEY_ALLOW; break; case CIL_AVRULE_AUDITALLOW: rulekind = CIL_KEY_AUDITALLOW; break; case CIL_AVRULE_DONTAUDIT: rulekind = CIL_KEY_DONTAUDIT; break; case CIL_AVRULE_NEVERALLOW: rulekind = CIL_KEY_NEVERALLOW; break; default: cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind); rc = SEPOL_ERR; goto exit; break; } src = avrule->src_str; tgt = avrule->tgt_str; rc = cil_unfill_classperms_list(avrule->perms.classperms, &classperms, 0); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, classperms); rc = SEPOL_OK; exit: free(classperms); return rc; } static int cil_write_avrule(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; struct cil_avrule *avrule = (struct cil_avrule *)node->data; if (avrule->is_extended) rc = cil_write_avrule_x(avrule, cil_out); else rc = cil_write_avrule_orig(avrule, cil_out); return rc; } static int cil_write_type_rule(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *type, *src, *tgt, *obj, *res; struct cil_type_rule *typerule = (struct cil_type_rule *)node->data; switch (typerule->rule_kind) { case CIL_TYPE_TRANSITION: type = CIL_KEY_TYPETRANSITION; break; case CIL_TYPE_MEMBER: type = CIL_KEY_TYPEMEMBER; break; case CIL_TYPE_CHANGE: type = CIL_KEY_TYPECHANGE; break; default: cil_log(CIL_ERR, "Unknown TYPERULE type: %d\n", typerule->rule_kind); rc = SEPOL_ERR; goto exit; break; } src = typerule->src_str; tgt = typerule->tgt_str; obj = typerule->obj_str; res = typerule->result_str; fprintf(cil_out, "(%s %s %s %s %s)\n", type, src, tgt, obj, res); rc = SEPOL_OK; exit: return rc; } static int cil_write_sens(struct cil_tree_node *node, FILE *cil_out) { struct cil_sens *sens = (struct cil_sens *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITY, sens->datum.name); return SEPOL_OK; } static int cil_write_cat(struct cil_tree_node *node, FILE *cil_out) { struct cil_cat *cat = (struct cil_cat *)node->data; fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATEGORY, cat->datum.name); return SEPOL_OK; } static int cil_write_senscat(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *sens; char *cats = NULL; struct cil_senscat *senscat = (struct cil_senscat *)node->data; sens = senscat->sens_str; rc = cil_unfill_cats(senscat->cats, &cats); if (rc != SEPOL_OK) goto exit; /* TODO: deal with extra/missing parens */ fprintf(cil_out, "(%s %s (%s))\n", CIL_KEY_SENSCAT, sens, cats); rc = SEPOL_OK; exit: free(cats); return rc; } static int cil_write_catorder(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *ord_str = NULL; struct cil_catorder *catord = (struct cil_catorder *)node->data; /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ rc = cil_unfill_expr(catord->cat_list_str, &ord_str, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATORDER, ord_str); rc = SEPOL_OK; exit: free(ord_str); return rc; } static int cil_write_sensorder(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *ord_str = NULL; struct cil_sensorder *sensord = (struct cil_sensorder *)node->data; /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ rc = cil_unfill_expr(sensord->sens_list_str, &ord_str, 1); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITYORDER, ord_str); rc = SEPOL_OK; exit: free(ord_str); return rc; } static int cil_write_genfscon(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; char *ctx_str = NULL; struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data; if (genfscon->context_str != NULL) { ctx_str = strdup(genfscon->context_str); if (ctx_str == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_context(genfscon->context, &ctx_str); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_GENFSCON, genfscon->fs_str, genfscon->path_str, ctx_str); rc = SEPOL_OK; exit: free(ctx_str); return rc; } static int cil_unfill_classperms(struct cil_list_item *curr, char **out_str) { int rc = SEPOL_ERR; size_t len = 3; char *class_str; char *perms_str = NULL; struct cil_classperms *cp = (struct cil_classperms *)curr->data; class_str = cp->class_str; len += strlen(class_str) + 1; /* fill_perms just calls gen_expr */ rc = cil_unfill_expr(cp->perm_strs, &perms_str, 1); if (rc != SEPOL_OK) goto exit; len += strlen(perms_str); *out_str = cil_malloc(len); sprintf(*out_str, "(%s %s)", class_str, perms_str); rc = SEPOL_OK; exit: free(perms_str); return rc; } static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren) { int rc = SEPOL_ERR; struct cil_list_item *curr; char *str = NULL; /* reuse cil_list to keep track of strings */ struct cil_list *str_list = NULL; cil_list_init(&str_list, CIL_NONE); cil_list_for_each(curr, classperms) { switch (curr->flavor) { case CIL_CLASSPERMS_SET: str = strdup(((struct cil_classperms_set *)curr->data)->set_str); if (str == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy classpermset.\n"); rc = SEPOL_ERR; goto exit; } break; case CIL_CLASSPERMS: rc = cil_unfill_classperms(curr, &str); if (rc != SEPOL_OK) goto exit; break; default: cil_log(CIL_ERR, "Unrecognized classperms flavor\n."); goto exit; } cil_list_append(str_list, CIL_STRING, (void *) str); str = NULL; } rc = __cil_strlist_concat(str_list, out_str, paren); if (rc != SEPOL_OK) goto exit; rc = SEPOL_OK; exit: cil_list_for_each(curr, str_list) { free(curr->data); } cil_list_destroy(&str_list, 0); return rc; } static int cil_write_fsuse(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data; char *type, *fsname; char *ctx_str = NULL; switch(fsuse->type) { case CIL_FSUSE_XATTR: type = CIL_KEY_XATTR; break; case CIL_FSUSE_TASK: type = CIL_KEY_TASK; break; case CIL_FSUSE_TRANS: type = CIL_KEY_TRANS; break; default: cil_log(CIL_ERR, "Unrecognized fsuse type\n"); rc = SEPOL_ERR; goto exit; break; } fsname = fsuse->fs_str; if (fsuse->context_str != NULL) { ctx_str = strdup(fsuse->context_str); if (ctx_str == NULL) { cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_unfill_context(fsuse->context, &ctx_str); if (rc != SEPOL_OK) goto exit; } fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_FSUSE, type, fsname, ctx_str); exit: free(ctx_str); return rc; } static int cil_write_constrain(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_ERR; struct cil_constrain *cons = (struct cil_constrain *)node->data; char *flav; char *classperms = NULL; char *expr = NULL; flav = (node->flavor == CIL_CONSTRAIN) ? CIL_KEY_CONSTRAIN : CIL_KEY_MLSCONSTRAIN; rc = cil_unfill_classperms_list(cons->classperms, &classperms, 0); if (rc != SEPOL_OK) goto exit; rc = cil_unfill_expr(cons->str_expr, &expr, 0); if (rc != SEPOL_OK) goto exit; fprintf(cil_out, "(%s %s %s)\n", flav, classperms, expr); exit: free(classperms); free(expr); return rc; } static int cil_write_handleunknown(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_OK; struct cil_handleunknown *handunknown = (struct cil_handleunknown *)node->data; char *val = NULL; switch (handunknown->handle_unknown) { case SEPOL_ALLOW_UNKNOWN: val = CIL_KEY_HANDLEUNKNOWN_ALLOW; break; case SEPOL_DENY_UNKNOWN: val = CIL_KEY_HANDLEUNKNOWN_DENY; break; case SEPOL_REJECT_UNKNOWN: val = CIL_KEY_HANDLEUNKNOWN_REJECT; break; default: cil_log(CIL_ERR, "Unknown handleunknown value: %d.\n", handunknown->handle_unknown); rc = SEPOL_ERR; goto exit; break; } fprintf(cil_out, "(%s %s)\n", CIL_KEY_HANDLEUNKNOWN, val); exit: return rc; } static int cil_write_mls(struct cil_tree_node *node, FILE *cil_out) { int rc = SEPOL_OK; struct cil_mls *mls = (struct cil_mls *)node->data; char *val = NULL; switch (mls->value) { case CIL_TRUE: val = CIL_KEY_CONDTRUE; break; case CIL_FALSE: val = CIL_KEY_CONDFALSE; break; default: cil_log(CIL_ERR, "Unknown mls value: %d.\n", mls->value); rc = SEPOL_ERR; goto exit; break; } fprintf(cil_out, "(%s %s)\n", CIL_KEY_MLS, val); exit: return rc; } static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_write *args = (struct cil_args_write *) extra_args; FILE *cil_out = NULL; if (node == NULL || extra_args == NULL) { goto exit; } cil_out = args->cil_out; if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) fprintf(cil_out,"("); rc = SEPOL_OK; exit: return rc; } static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_OK; struct cil_args_write *args = NULL; FILE *cil_out = NULL; if (node == NULL || extra_args == NULL) { goto exit; } args = extra_args; cil_out = args->cil_out; switch (node->flavor) { case CIL_BLOCK: rc = cil_write_unsupported("CIL_BLOCK"); break; case CIL_BLOCKABSTRACT: rc = cil_write_unsupported("CIL_BLOCKABSTRACT"); break; case CIL_BLOCKINHERIT: rc = cil_write_unsupported("CIL_BLOCKINHERIT"); break; case CIL_IN: rc = cil_write_unsupported("CIL_IN"); break; case CIL_POLICYCAP: cil_write_policycap(node, cil_out); break; case CIL_PERM: rc = cil_write_perm(node, cil_out); break; case CIL_MAP_PERM: rc = cil_write_unsupported("CIL_MAP_PERM"); break; case CIL_CLASSMAPPING: rc = cil_write_unsupported("CIL_CLASSMAPPING"); break; case CIL_CLASS: rc = cil_write_class(node, finished, extra_args); break; case CIL_COMMON: rc = cil_write_class(node, finished, extra_args); break; case CIL_MAP_CLASS: rc = cil_write_unsupported("CIL_MAP_CLASS"); break; case CIL_CLASSORDER: rc = cil_write_classorder(node, cil_out); break; case CIL_CLASSPERMISSION: rc = cil_write_unsupported("CIL_CLASSPERMISSION"); break; case CIL_CLASSPERMISSIONSET: rc = cil_write_unsupported("CIL_CLASSPERMISSIONSET"); break; case CIL_CLASSCOMMON: rc = cil_write_classcommon(node, cil_out); break; case CIL_SID: rc = cil_write_sid(node, cil_out); break; case CIL_SIDCONTEXT: rc = cil_write_sidcontext(node, cil_out); break; case CIL_SIDORDER: rc = cil_write_sidorder(node, cil_out); break; case CIL_USER: rc = cil_write_user(node, cil_out); break; case CIL_USERATTRIBUTE: rc = cil_write_unsupported("CIL_USERATTRIBUTE"); break; case CIL_USERATTRIBUTESET: rc = cil_write_unsupported("CIL_USERATTRIBUTESET"); break; case CIL_USERROLE: rc = cil_write_userrole(node, cil_out); break; case CIL_USERLEVEL: rc = cil_write_userlevel(node, cil_out); break; case CIL_USERRANGE: rc = cil_write_userrange(node, cil_out); break; case CIL_USERBOUNDS: rc = cil_write_unsupported("CIL_USERBOUNDS"); break; case CIL_USERPREFIX: rc = cil_write_unsupported("CIL_USERPREFIX"); break; case CIL_ROLE: rc = cil_write_role(node, cil_out); break; case CIL_ROLETYPE: rc = cil_write_roletype(node, cil_out); break; case CIL_ROLEBOUNDS: rc = cil_write_unsupported("CIL_ROLEBOUNDS"); break; case CIL_ROLEATTRIBUTE: cil_write_roleattribute(node, cil_out); break; case CIL_ROLEATTRIBUTESET: rc = cil_write_unsupported("CIL_ROLEATTRIBUTESET"); break; case CIL_ROLEALLOW: rc = cil_write_unsupported("CIL_ROLEALLOW"); break; case CIL_TYPE: rc = cil_write_type(node, cil_out); break; case CIL_TYPEBOUNDS: rc = cil_write_unsupported("CIL_TYPEBOUNDS"); break; case CIL_TYPEPERMISSIVE: rc = cil_write_typepermissive(node, cil_out); break; case CIL_TYPEATTRIBUTE: rc = cil_write_typeattribute(node, cil_out); break; case CIL_TYPEATTRIBUTESET: rc = cil_write_typeattributeset(node, cil_out); break; case CIL_EXPANDTYPEATTRIBUTE: rc = cil_write_expandtypeattribute(node, cil_out); break; case CIL_TYPEALIAS: rc = cil_write_alias(node, cil_out); break; case CIL_TYPEALIASACTUAL: rc = cil_write_aliasactual(node, cil_out); break; case CIL_ROLETRANSITION: rc = cil_write_unsupported("CIL_ROLETRANSITION"); break; case CIL_NAMETYPETRANSITION: rc = cil_write_nametypetransition(node, cil_out); break; case CIL_RANGETRANSITION: rc = cil_write_unsupported("CIL_RANGETRANSITION"); break; case CIL_TUNABLE: rc = cil_write_unsupported("CIL_TUNABLE"); break; case CIL_BOOL: rc = cil_write_unsupported("CIL_BOOL"); break; case CIL_AVRULE: case CIL_AVRULEX: rc = cil_write_avrule(node, cil_out); break; case CIL_PERMISSIONX: rc = cil_write_unsupported("CIL_PERMISSIONX"); break; case CIL_TYPE_RULE: cil_write_type_rule(node, cil_out); break; case CIL_SENS: rc = cil_write_sens(node, cil_out); break; case CIL_SENSALIAS: rc = cil_write_alias(node, cil_out); break; case CIL_SENSALIASACTUAL: rc = cil_write_aliasactual(node, cil_out); break; case CIL_CAT: rc = cil_write_cat(node, cil_out); break; case CIL_CATALIAS: rc = cil_write_alias(node, cil_out); break; case CIL_CATALIASACTUAL: rc = cil_write_aliasactual(node, cil_out); break; case CIL_CATSET: rc = cil_write_unsupported("CIL_CATSET"); break; case CIL_SENSCAT: rc = cil_write_senscat(node, cil_out); break; case CIL_CATORDER: rc = cil_write_catorder(node, cil_out); break; case CIL_SENSITIVITYORDER: rc = cil_write_sensorder(node, cil_out); break; case CIL_LEVEL: rc = cil_write_unsupported("CIL_LEVEL"); break; case CIL_LEVELRANGE: rc = cil_write_unsupported("CIL_LEVELRANGE"); break; case CIL_CONTEXT: rc = cil_write_unsupported("CIL_CONTEXT"); break; case CIL_NETIFCON: rc = cil_write_unsupported("CIL_NETIFCON"); break; case CIL_GENFSCON: rc = cil_write_genfscon(node, cil_out); break; case CIL_FILECON: rc = cil_write_unsupported("CIL_FILECON"); break; case CIL_NODECON: rc = cil_write_unsupported("CIL_NODECON"); break; case CIL_PORTCON: rc = cil_write_unsupported("CIL_PORTCON"); break; case CIL_PIRQCON: rc = cil_write_unsupported("CIL_PIRQCON"); break; case CIL_IOMEMCON: rc = cil_write_unsupported("CIL_IOMEMCON"); break; case CIL_IOPORTCON: rc = cil_write_unsupported("CIL_IOPORTCON"); break; case CIL_PCIDEVICECON: rc = cil_write_unsupported("CIL_PCIDEVICECON"); break; case CIL_DEVICETREECON: rc = cil_write_unsupported("CIL_DEVICETREECON"); break; case CIL_FSUSE: rc = cil_write_fsuse(node, cil_out); break; case CIL_CONSTRAIN: rc = cil_write_unsupported("CIL_CONSTRAIN"); break; case CIL_MLSCONSTRAIN: rc = cil_write_constrain(node, cil_out); break; case CIL_VALIDATETRANS: rc = cil_write_unsupported("CIL_VALIDATETRANS"); break; case CIL_MLSVALIDATETRANS: rc = cil_write_unsupported("CIL_MLSVALIDATETRANS"); break; case CIL_CALL: rc = cil_write_unsupported("CIL_CALL"); break; case CIL_MACRO: rc = cil_write_unsupported("CIL_MACRO"); break; case CIL_NODE: rc = cil_write_unsupported("CIL_NODE"); break; case CIL_OPTIONAL: rc = cil_write_unsupported("CIL_OPTIONAL"); break; case CIL_IPADDR: rc = cil_write_unsupported("CIL_IPADDR"); break; case CIL_CONDBLOCK: rc = cil_write_unsupported("CIL_CONDBLOCK"); break; case CIL_BOOLEANIF: rc = cil_write_unsupported("CIL_BOOLEANIF"); break; case CIL_TUNABLEIF: rc = cil_write_unsupported("CIL_TUNABLEIF"); break; case CIL_DEFAULTUSER: rc = cil_write_unsupported("CIL_DEFAULTUSER"); break; case CIL_DEFAULTROLE: rc = cil_write_unsupported("CIL_DEFAULTROLE"); break; case CIL_DEFAULTTYPE: rc = cil_write_unsupported("CIL_DEFAULTTYPE"); break; case CIL_DEFAULTRANGE: rc = cil_write_unsupported("CIL_DEFAULTRANGE"); break; case CIL_SELINUXUSER: rc = cil_write_unsupported("CIL_SELINUXUSER"); break; case CIL_SELINUXUSERDEFAULT: rc = cil_write_unsupported("CIL_SELINUXUSERDEFAULT"); break; case CIL_HANDLEUNKNOWN: rc = cil_write_handleunknown(node, cil_out); break; case CIL_MLS: rc = cil_write_mls(node, cil_out); break; case CIL_SRC_INFO: break; case CIL_NONE: // TODO: add proper removal support *finished = CIL_TREE_SKIP_HEAD; break; default: cil_log(CIL_ERR, "Unknown AST flavor: %d.\n", node->flavor); rc = SEPOL_ERR; goto exit; break; } exit: return rc; } static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args) { int rc = SEPOL_ERR; struct cil_args_write *args = NULL; FILE *cil_out = NULL; if (node == NULL || extra_args == NULL) { goto exit; } args = extra_args; cil_out = args->cil_out; if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) { fprintf(cil_out,")"); } rc = SEPOL_OK; exit: return rc; } /* main exported function */ int cil_write_ast(struct cil_db *db, const char* path) { int rc = SEPOL_ERR; struct cil_args_write extra_args; FILE *cil_out = NULL; cil_out = fopen(path, "we"); if (cil_out == NULL) { cil_log(CIL_ERR, "Failure opening output file for writing AST\n"); rc = SEPOL_ERR; goto exit; } extra_args.cil_out = cil_out; extra_args.db = db; rc = cil_tree_walk(db->ast->root, __cil_write_node_helper, __cil_write_first_child_helper, __cil_write_last_child_helper, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); goto exit; } exit: fclose(cil_out); cil_out = NULL; return rc; } libsepol/cil/src/dso.h0100644 0000000 0000000 00000001350 13756670065 013730 0ustar000000000 0000000 #ifndef _SEPOL_DSO_H #define _SEPOL_DSO_H 1 #if !defined(SHARED) || defined(ANDROID) || defined(__APPLE__) #define DISABLE_SYMVER 1 #endif #ifdef SHARED # define hidden __attribute__ ((visibility ("hidden"))) # define hidden_proto(fct) __hidden_proto (fct, fct##_internal) # define __hidden_proto(fct, internal) \ extern __typeof (fct) internal; \ extern __typeof (fct) fct __asm (#internal) hidden; # if defined(__alpha__) || defined(__mips__) # define hidden_def(fct) \ asm (".globl " #fct "\n" #fct " = " #fct "_internal"); # else # define hidden_def(fct) \ asm (".globl " #fct "\n.set " #fct ", " #fct "_internal"); #endif #else # define hidden # define hidden_proto(fct) # define hidden_def(fct) #endif #endif libsepol/cil/test/0040755 0000000 0000000 00000000000 13756670065 013166 5ustar000000000 0000000 libsepol/cil/test/integration_testing/0040755 0000000 0000000 00000000000 13756670065 017246 5ustar000000000 0000000 libsepol/cil/test/integration_testing/mls_policy.cil0100644 0000000 0000000 00000004711 13756670065 022111 0ustar000000000 0000000 (class testing (read open close write exec)) (class fooclass (read open close write exec)) (category c0) (category c1) (category c2) (category c3) (category c4) (categoryalias c0 cat) (categoryorder (c0 c1 c2 c3 c4)) (categoryset catset (c0 c2 c3)) (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivityalias s3 sens) (dominance (s0 s1 s2 s3)) (sensitivitycategory s0 (c0 c2 c3)) (sensitivitycategory s0 (cat)) ; the following causes a segfault ;(sensitivitycategory sens (c2)) (type foo_t) (type typea_t) (type typeb_t) (type typec_t) (role foo_r) (role rolea_r) (role roleb_r) (user foo_u) (user user_u) (userrole foo_u foo_r) (level low (s0 catset)) (level high (s0 (c0))) (level test_l (s0 (cat))) (sid test_sid) (sidcontext test_sid (foo_u foo_r foo_t (s0 (c0)) (s0 (c0)))) (sid test_sid_anon_l) (sidcontext test_sid_anon_l (foo_u foo_r foo_t low high)) (context con (foo_u foo_r foo_t low high)) (context con_anon_l (foo_u foo_r foo_t (s0 (c0)) high)) (fsuse xattr ext3 con) (fsuse xattr ext3 con_anon_l) (netifcon eth0 con con_anon_l) (ipaddr ip_v4 192.25.35.200) (ipaddr netmask 192.168.1.1) (ipaddr ip_v6 2001:0DB8:AC10:FE01::) (ipaddr netmask_v6 2001:0DE0:DA88:2222::) ; will need anon levels (nodecon ip_v4 netmask con) (nodecon ip_v6 netmask_v6 con_anon_l) ;needs anon levels (portcon type 25 con) (filecon root path file con) (genfscon type path con) (netifcon eth0 con con_anon_l) (typemember typea_t typeb_t testing typec_t) (typechange typea_t typeb_t testing typec_t) (typetransition typea_t typeb_t testing typec_t) (permissionset permset (open close)) (allow typea_t typeb_t testing (write)) (allow typea_t typeb_t testing permset) (roleallow rolea_r roleb_r) (rolebounds rolea_r roleb_r) (roletransition foo_r foo_t testing rolea_r) (level l2 (s0 (c0))) (level h2 (s0 (c0))) (mlsconstrain (fooclass testing)(open close)(eq l2 h2)) (common fooclass (open)) (classcommon fooclass fooclass) (rangetransition typea_t typeb_t fooclass low high) (nametypetransition string typea_t typeb_t fooclass foo_t) (typepermissive foo_t) (typebounds typea_t typeb_t) (block test_b (typealias .test_b.test typea_t) (type test)) (attribute attrs) (attributetypes attrs (foo_t)) (roletype foo_r foo_t) (userbounds user_u foo_u) (userrole user_u foo_r) (bool foo_b true) (bool baz_b false) (booleanif (&& foo_b baz_b) (allow typea_t typeb_t fooclass(read))) ;(class baz (read)) ;(booleanif (&& foo_b baz_b) ; (allow foo_b baz_b fooclass (read))) libsepol/cil/test/integration_testing/nonmls.cil0100644 0000000 0000000 00000003276 13756670065 021252 0ustar000000000 0000000 (class testing (read open close write exec)) (class fooclass (read open close write exec)) (type foo_t) (type typea_t) (type typeb_t) (type typec_t) (role foo_r) (role rolea_r) (role roleb_r) (user foo_u) (user user_u) (userrole foo_u foo_r) (sid test_sid) ;(sidcontext test_sid (foo_u foo_r foo_t (s0 (c0)) (s0 (c0)))) ;(sid test_sid_anon_l) ;(fsuse xattr ext3 con) ;(fsuse xattr ext3 con_anon_l) ;(netifcon eth0 con con_anon_l) (ipaddr ip_v4 192.25.35.200) (ipaddr netmask 192.168.1.1) (ipaddr ip_v6 2001:0DB8:AC10:FE01::) (ipaddr netmask_v6 2001:0DE0:DA88:2222::) ; will need anon levels ;(nodecon ip_v4 netmask con) ;(nodecon ip_v6 netmask_v6 con_anon_l) ;needs anon levels ;(portcon type 25 con) ;(filecon root path file con) ;(genfscon type path con) ;(netifcon eth0 con con_anon_l) (typemember typea_t typeb_t testing typec_t) (typechange typea_t typeb_t testing typec_t) (typetransition typea_t typeb_t testing typec_t) (permissionset permset (open close)) (allow typea_t typeb_t testing (write)) (allow typea_t typeb_t testing permset) (roleallow rolea_r roleb_r) (rolebounds rolea_r roleb_r) (roletransition foo_r foo_t testing rolea_r) (common fooclass (open)) (classcommon fooclass fooclass) (nametypetransition string typea_t typeb_t fooclass foo_t) (typepermissive foo_t) (typebounds typea_t typeb_t) (block test_b (typealias .test_b.test typea_t) (type test)) (attribute attrs) (attributetypes attrs (foo_t)) (roletype foo_r foo_t) (userbounds user_u foo_u) (userrole user_u foo_r) ;(bool foo_b true) ;(bool baz_b false) ;(booleanif (&& foo_b baz_b) ; (allow typea_t typeb_t fooclass(read))) ;(class baz (read)) ;(booleanif (&& foo_b baz_b) ; (allow foo_b baz_b fooclass (read))) libsepol/cil/test/integration_testing/nonmls.conf0100644 0000000 0000000 00000001370 13756670065 021421 0ustar000000000 0000000 class testing class fooclass sid test_sid #end #sid decl sid security class testing { read open close write exec } class fooclass { read open close write exec } #end #attribs attribute attrs; #end type foo_t, attrs; type typea_t; type typeb_t; type typec_t; #end bool foo_b true; bool baz_b false; #end role foo_r types foo_t; role rolea_r; role roleb_r; #end #role decl allow typea_t typeb_t : testing write; allow typea_t typeb_t : testing {open close}; type_transition typea_t typeb_t : testing typec_t; #end #audit rules #dontaudit {kernel} unknown : dir search; allow rolea_r roleb_r; #end #rbac stuff #allow system {guest local_user}; #allow local_user guest; user foo_u roles foo_r; #end sid test_sid foo_u:foo_r:foo_t libsepol/cil/test/integration_testing/ordered_lists_bad1.cil0100644 0000000 0000000 00000001305 13756670065 023464 0ustar000000000 0000000 ; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol/cil/test/integration_testing/ordered_lists_bad2.cil0100644 0000000 0000000 00000001302 13756670065 023462 0ustar000000000 0000000 ; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) libsepol/cil/test/integration_testing/ordered_lists_bad3.cil0100644 0000000 0000000 00000001326 13756670065 023471 0ustar000000000 0000000 ; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol/cil/test/integration_testing/ordered_lists_easy.cil0100644 0000000 0000000 00000001146 13756670065 023621 0ustar000000000 0000000 ; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s0 s1 s2 s3 s4 s5 s6 s7 s8 s9)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c2 c3 c4 c5)) (categoryorder (c0 c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c7 c8 c9)) libsepol/cil/test/integration_testing/ordered_lists_hard.cil0100644 0000000 0000000 00000001331 13756670065 023572 0ustar000000000 0000000 ; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol/cil/test/integration_testing/small.cil0100644 0000000 0000000 00000000076 13756670065 021047 0ustar000000000 0000000 (class foo (read)) (type bar) (allow bar self (foo (read))) libsepol/cil/test/unit/0040755 0000000 0000000 00000000000 13756670065 014145 5ustar000000000 0000000 libsepol/cil/test/unit/AllTests.c0100644 0000000 0000000 00000005573 13756670065 016053 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "../../src/cil_log.h" CuSuite* CilTreeGetSuite(void); CuSuite* CilTreeGetResolveSuite(void); CuSuite* CilTreeGetBuildSuite(void); CuSuite* CilTestFullCil(void); void RunAllTests(void) { /* disable cil log output */ cil_set_log_level(0); CuString *output = CuStringNew(); CuSuite* suite = CuSuiteNew(); CuSuite* suiteResolve = CuSuiteNew(); CuSuite* suiteBuild = CuSuiteNew(); CuSuite* suiteIntegration = CuSuiteNew(); CuSuiteAddSuite(suite, CilTreeGetSuite()); CuSuiteAddSuite(suiteResolve, CilTreeGetResolveSuite()); CuSuiteAddSuite(suiteBuild, CilTreeGetBuildSuite()); CuSuiteAddSuite(suiteIntegration, CilTestFullCil()); CuSuiteRun(suite); CuSuiteDetails(suite, output); CuSuiteSummary(suite, output); CuSuiteRun(suiteResolve); CuSuiteDetails(suiteResolve, output); CuSuiteSummary(suiteResolve, output); CuSuiteRun(suiteBuild); CuSuiteDetails(suiteBuild, output); CuSuiteSummary(suiteBuild, output); CuSuiteRun(suiteIntegration); CuSuiteDetails(suiteIntegration, output); CuSuiteSummary(suiteIntegration, output); printf("\n%s\n", output->buffer); } int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) { RunAllTests(); return 0; } libsepol/cil/test/unit/CilTest.c0100644 0000000 0000000 00000315053 13756670065 015664 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "test_cil.h" #include "test_cil_tree.h" #include "test_cil_list.h" #include "test_cil_symtab.h" #include "test_cil_parser.h" #include "test_cil_lexer.h" #include "test_cil_build_ast.h" #include "test_cil_resolve_ast.h" #include "test_cil_fqn.h" #include "test_cil_copy_ast.h" #include "test_cil_post.h" #include "test_integration.h" void set_cil_file_data(struct cil_file_data **data) { struct cil_file_data *new_data = malloc(sizeof(*new_data)); FILE *file; struct stat filedata; uint32_t file_size; char *buffer; file = fopen("test/policy.cil", "r"); if (!file) { fprintf(stderr, "Could not open file\n"); exit(1); } if (stat("test/policy.cil", &filedata) == -1) { printf("Could not stat file\n"); exit(1); } file_size = filedata.st_size; buffer = malloc(file_size + 2); if(fread(buffer, file_size, 1, file) < 1) { exit(1); } memset(buffer+file_size, 0, 2); fclose(file); new_data->buffer = buffer; new_data->file_size = file_size; *data = new_data; } void gen_test_tree(struct cil_tree **test_root, char *line[]) { struct cil_tree *new_tree = malloc(sizeof(*new_tree)); struct cil_tree_node *node, *item, *current; cil_tree_init(&new_tree); new_tree->root->flavor = CIL_ROOT; current = new_tree->root; char **i = line; do { if (*i[0] == '(') { cil_tree_node_init(&node); node->parent = current; node->flavor = CIL_PARSE_NODE; node->line = 0; if (current->cl_head == NULL) current->cl_head = node; else current->cl_tail->next = node; current->cl_tail = node; current = node; } else if (*i[0] == ')') current = current->parent; else { cil_tree_node_init(&item); item->parent = current; item->data = cil_strdup(*i); item->flavor = CIL_PARSE_NODE; item->line = 0; if (current->cl_head == NULL) { current->cl_head = item; } else { current->cl_tail->next = item; } current->cl_tail = item; } i++; } while(*i != NULL); *test_root = new_tree; } void test_symtab_init(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); uint32_t rc = 0, i =0; for (i = 0; i < CIL_SYM_NUM; i++) { rc = symtab_init(&test_new_db->symtab[i], cil_sym_sizes[CIL_SYM_ARRAY_ROOT][i]); CuAssertIntEquals(tc, 0, rc); // TODO CDS add checks to make sure the symtab looks correct } free(test_new_db); } void test_symtab_init_no_table_neg(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); int rc = symtab_init(&test_new_db->symtab[0], (uint32_t)SIZE_MAX); CuAssertIntEquals(tc, -1, rc); free(test_new_db); } CuSuite* CilTreeGetResolveSuite(void) { CuSuite* suite = CuSuiteNew(); /* test_cil_resolve_ast.c */ SUITE_ADD_TEST(suite, test_cil_resolve_ast_curr_null_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes_inval_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name); SUITE_ADD_TEST(suite, test_cil_resolve_name_invalid_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_type_in_multiple_attrs); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_multiple_excludes_with_not); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_multiple_types_with_and); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_using_attr); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_name_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_undef_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_not); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_undef_type_not_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typeattributeset); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typealias); SUITE_ADD_TEST(suite, test_cil_resolve_typealias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typealias_notype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_repeatbind_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_type1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_type2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typebounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typebounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typepermissive); SUITE_ADD_TEST(suite, test_cil_resolve_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typepermissive); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_src_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_tgt_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_dest_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nametypetransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nametypetransition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_type1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_type2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_l_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_l_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_h_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_h_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_level_l_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_level_h_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_l); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_l_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_h); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_h_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rangetransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rangetransition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon_no_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon_no_common_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_classcommon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_classcommon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_named); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_inmacro); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_inmacro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_named_classmapname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_classmapname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_permset_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_exists_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_role1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_role2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rolebounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rolebounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sensalias); SUITE_ADD_TEST(suite, test_cil_resolve_sensalias_sensdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sensalias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catalias); SUITE_ADD_TEST(suite, test_cil_resolve_catalias_catdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catalias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catorder); SUITE_ADD_TEST(suite, test_cil_resolve_catorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_dominance); SUITE_ADD_TEST(suite, test_cil_resolve_dominance_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_dominance); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_dominance_neg); //TODO: test for __cil_set_order SUITE_ADD_TEST(suite, test_cil_resolve_catset); SUITE_ADD_TEST(suite, test_cil_resolve_catset_catlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catset); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catset_catlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_catloworder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cathighorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cat1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cat2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catsetname); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catsetname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_sublist); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_missingsens_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_category_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_currrangecat); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_senscat); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_senscat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level); SUITE_ADD_TEST(suite, test_cil_resolve_level_catlist); SUITE_ADD_TEST(suite, test_cil_resolve_level_catset); SUITE_ADD_TEST(suite, test_cil_resolve_level_catset_name_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_sens_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_cat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_senscat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_level); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl_low_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl_high_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl_low_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl_high_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_levelrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_levelrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_perm_resolve_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_constrain); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_constrain_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_mlsconstrain); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_mlsconstrain_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context); SUITE_ADD_TEST(suite, test_cil_resolve_context_macro); SUITE_ADD_TEST(suite, test_cil_resolve_context_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_namedrange); SUITE_ADD_TEST(suite, test_cil_resolve_context_namedrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_anon_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_context); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roleallow); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roleallow_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_namedpermlist); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_permlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_unnamedcps_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon_namedpermlist); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon_permlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset_permdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_firsttype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_secondtype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_src_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_class_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_datum_null_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_transition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_change); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_change_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_member); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_member_neg); SUITE_ADD_TEST(suite, test_cil_resolve_filecon); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_filecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_filecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_portcon); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_portcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_portcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_genfscon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonipaddr_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonnetmask_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonipaddr_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonnetmask_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_diffipfam_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_netmask_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon_netmask_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_otf_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_interface_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed_packet_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed_otf_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_netifcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_netifcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pirqcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pirqcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_iomemcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_iomemcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_ioportcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_ioportcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pcidevicecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_anon); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_fsuse); //SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_levels); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context_wrongname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context_invaliduser_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sidcontext_neg); SUITE_ADD_TEST(suite, test_cil_resolve_blockinherit); SUITE_ADD_TEST(suite, test_cil_resolve_blockinherit_blockstrdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_blockinherit); SUITE_ADD_TEST(suite, test_cil_resolve_in_block); SUITE_ADD_TEST(suite, test_cil_resolve_in_blockstrdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_in_macro); SUITE_ADD_TEST(suite, test_cil_resolve_in_optional); //SUITE_ADD_TEST(suite, test_cil_resolve_call1_noparam); SUITE_ADD_TEST(suite, test_cil_resolve_call1_type); SUITE_ADD_TEST(suite, test_cil_resolve_call1_role); SUITE_ADD_TEST(suite, test_cil_resolve_call1_user); SUITE_ADD_TEST(suite, test_cil_resolve_call1_sens); SUITE_ADD_TEST(suite, test_cil_resolve_call1_cat); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_class); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classmap); SUITE_ADD_TEST(suite, test_cil_resolve_call1_permset); SUITE_ADD_TEST(suite, test_cil_resolve_call1_permset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknown_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknowncall_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_extraargs_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_copy_dup); SUITE_ADD_TEST(suite, test_cil_resolve_call1_missing_arg_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_paramsflavor_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknownflavor_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call1); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call2_type); SUITE_ADD_TEST(suite, test_cil_resolve_call2_role); SUITE_ADD_TEST(suite, test_cil_resolve_call2_user); SUITE_ADD_TEST(suite, test_cil_resolve_call2_sens); SUITE_ADD_TEST(suite, test_cil_resolve_call2_cat); SUITE_ADD_TEST(suite, test_cil_resolve_call2_catset); SUITE_ADD_TEST(suite, test_cil_resolve_call2_catset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_permset); SUITE_ADD_TEST(suite, test_cil_resolve_call2_permset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_class); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classmap); SUITE_ADD_TEST(suite, test_cil_resolve_call2_level); SUITE_ADD_TEST(suite, test_cil_resolve_call2_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_ipaddr); SUITE_ADD_TEST(suite, test_cil_resolve_call2_ipaddr_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_unknown_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call2); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_multipleparams); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_diffflavor); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_callnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_namenull_neg); //SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_callargsnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_name_neg); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_bools); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_tunables); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_type); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_role); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_user); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_neg); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_emptystr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_boolif); SUITE_ADD_TEST(suite, test_cil_resolve_boolif_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_boolif_neg); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_xor); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_eq); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_neq); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_oper1); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_oper2); //SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_neg); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_false); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_true); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_resolveexpr_neg); //SUITE_ADD_TEST(suite, test_cil_resolve_tunif_evaluateexpr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_tunif); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_tunif_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_exists_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_user1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_user2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userbounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userbounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletype); SUITE_ADD_TEST(suite, test_cil_resolve_roletype_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletype_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrole); SUITE_ADD_TEST(suite, test_cil_resolve_userrole_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrole_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_macro); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userlevel); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userlevel_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_macro); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_anon); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrange_neg); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_optional_enabled); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_optional_disabled); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_block); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_user); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_role); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_type); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_typealias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_common); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_class); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_bool); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sens); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_cat); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_catset); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sid); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_macro); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_context); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_level); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_policycap); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_perm); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_catalias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_tunable); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_unknown); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_callstack); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optional); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_macro); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack_tunable_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_extraargsnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optfailedtoresolve); return suite; } CuSuite* CilTreeGetBuildSuite(void) { CuSuite* suite = CuSuiteNew(); /* test_cil_build_ast.c */ SUITE_ADD_TEST(suite, test_cil_build_ast); SUITE_ADD_TEST(suite, test_cil_build_ast_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_treenull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_suberr_neg); SUITE_ADD_TEST(suite, test_cil_parse_to_list); SUITE_ADD_TEST(suite, test_cil_parse_to_list_currnull_neg); SUITE_ADD_TEST(suite, test_cil_parse_to_list_listnull_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list); SUITE_ADD_TEST(suite, test_cil_set_to_list_listnull_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list_tree_node_null_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list_cl_head_null_neg); SUITE_ADD_TEST(suite, test_cil_gen_block); SUITE_ADD_TEST(suite, test_cil_gen_block_justblock_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_treenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_nodeparentnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_block); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_block_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_namelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_blockinherit); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_blockinherit_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm); SUITE_ADD_TEST(suite, test_cil_gen_perm_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset); SUITE_ADD_TEST(suite, test_cil_gen_permset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_permset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_permset_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes_failgen_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset); SUITE_ADD_TEST(suite, test_cil_fill_permset_sublist_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset_startpermnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset_permsetnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in); SUITE_ADD_TEST(suite, test_cil_gen_in_blockstrnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_in); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_in_neg); SUITE_ADD_TEST(suite, test_cil_gen_class); SUITE_ADD_TEST(suite, test_cil_gen_class_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_noclassname_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_namesublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_noperms); SUITE_ADD_TEST(suite, test_cil_gen_class_permsnotinlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_extrapermlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_listinlist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_class); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_class_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_anonperms); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_anonperms_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_namedperms); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_extra_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_emptypermslist_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_classnodenull_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_cpsnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classpermset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classpermset_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_dupeperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap); SUITE_ADD_TEST(suite, test_cil_gen_classmap_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmap); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmap_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_anonpermset); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_anonpermset_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_namedpermset); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_noclassmapname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_noclassmapperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_nopermissionsets_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmapping); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmapping_neg); SUITE_ADD_TEST(suite, test_cil_gen_common); SUITE_ADD_TEST(suite, test_cil_gen_common_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_twoperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_permsublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_noperms_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_common); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_common_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid); SUITE_ADD_TEST(suite, test_cil_gen_sid_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sid); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sid_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_namedcontext); // SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_halfcontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_dblname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_pcurrnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_astnodenull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sidcontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_type); SUITE_ADD_TEST(suite, test_cil_gen_type_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattribute); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattribute_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_notype1_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_type1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_notype2_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_type2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typebounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typebounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typepermissive); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nostr_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_strinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nosrc_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_srcinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_notgt_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_tgtinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_classinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nodest_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_destinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_nametypetransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_nametypetransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_namedtransition); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_low_l); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_low_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_high_l); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_high_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nofirsttype_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_firsttype_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nosecondtype_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_secondtype_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_class_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nolevel_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nolevel_h_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rangetransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rangetransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_xor); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_eq); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_neq); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_emptyargs_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_missingoperator_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_arg1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_arg2null_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_extraarg_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_stacknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_true); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_false); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_true); SUITE_ADD_TEST(suite, test_cil_gen_boolif_false); SUITE_ADD_TEST(suite, test_cil_gen_boolif_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nested); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_extra_parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nocond); SUITE_ADD_TEST(suite, test_cil_gen_boolif_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_notruelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_empty_cond_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_boolif_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_true); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_false); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_true); SUITE_ADD_TEST(suite, test_cil_gen_tunif_false); SUITE_ADD_TEST(suite, test_cil_gen_tunif_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nocond); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nested); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_extra_parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_notruelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_tunif); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_true); SUITE_ADD_TEST(suite, test_cil_gen_condblock_false); SUITE_ADD_TEST(suite, test_cil_gen_condblock_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_true); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_true_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_false); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_false_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias); SUITE_ADD_TEST(suite, test_cil_gen_typealias_incomplete_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_incomplete_neg2); SUITE_ADD_TEST(suite, test_cil_gen_typealias_extratype_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typealias_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_and_two_types); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_not); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_exclude_attr); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_exclude_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_emptylists_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_listinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattributeset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattributeset_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_notype1_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_type1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_notype2_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_type2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userbounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userbounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_role); SUITE_ADD_TEST(suite, test_cil_gen_role_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_extrarole_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_noname_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_role); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_role_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_true); SUITE_ADD_TEST(suite, test_cil_gen_bool_tunable_true); SUITE_ADD_TEST(suite, test_cil_gen_bool_false); SUITE_ADD_TEST(suite, test_cil_gen_bool_tunable_false); SUITE_ADD_TEST(suite, test_cil_gen_bool_none_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_notbool_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_boolname_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_extraname_false_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_extraname_true_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_tunable); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_tunable_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1type); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1t1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t2type); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t2t2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1role); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1r1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r2role); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r2r2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1t2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_r1r2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1r2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1u2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1user); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1u1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u2user); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u2u2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l2h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1h1); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1l2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_emptyparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_extraparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_stacknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_operatorinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incorrectcall_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roleallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roleallow_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_norole1_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_role1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_norole2_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_role2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rolebounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rolebounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permset); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permset_anon); SUITE_ADD_TEST(suite, test_cil_gen_avrule_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourceparens); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourceemptyparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetparens); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetemptyparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourcedomainnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetdomainnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_objectclassnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permsnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_twolists_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_allow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_allow_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_auditallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_auditallow_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_dontaudit); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_dontaudit_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_neverallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_neverallow_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_transition_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_change); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_change_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_member); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_member_neg); SUITE_ADD_TEST(suite, test_cil_gen_user); SUITE_ADD_TEST(suite, test_cil_gen_user_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_nouser_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_xsinfo_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_user); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_user_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_anon_level); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_anon_level_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_usernull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_userrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_levelnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_levelrangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userlevel); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userlevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_named); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anon); SUITE_ADD_TEST(suite, test_cil_gen_userrange_usernull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonuser_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_rangenamenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonrangeinvalid_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonrangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_senslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensitivity); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensitivity_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_senslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_aliasnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_aliaslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensalias_neg); SUITE_ADD_TEST(suite, test_cil_gen_category); SUITE_ADD_TEST(suite, test_cil_gen_category_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_catnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_catlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_category); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_category_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset); SUITE_ADD_TEST(suite, test_cil_gen_catset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_setnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_namelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_nodefail_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_notset_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_settolistfail_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catset_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias); SUITE_ADD_TEST(suite, test_cil_gen_catalias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_catnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_aliasnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catalias_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange); SUITE_ADD_TEST(suite, test_cil_gen_catrange_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_norange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_emptyrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_extrarange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype); SUITE_ADD_TEST(suite, test_cil_gen_roletype_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_rolelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_roletype_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_typelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletype); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletype_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole); SUITE_ADD_TEST(suite, test_cil_gen_userrole_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_userlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_userrole_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_rolelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrole_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_missingclassname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_extraperms_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_classcommon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_classcommon_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder); SUITE_ADD_TEST(suite, test_cil_gen_catorder_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_missingcats_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_nosublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_nestedcat_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catorder_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance); SUITE_ADD_TEST(suite, test_cil_gen_dominance_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_nosensitivities_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_nosublist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_dominance); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_dominance_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nosublist); SUITE_ADD_TEST(suite, test_cil_gen_senscat_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nosensitivities_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nocat_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_senscat); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_senscat_neg); SUITE_ADD_TEST(suite, test_cil_fill_level); SUITE_ADD_TEST(suite, test_cil_fill_level_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_level_levelnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_level_nocat); SUITE_ADD_TEST(suite, test_cil_fill_level_emptycat_neg); SUITE_ADD_TEST(suite, test_cil_gen_level); SUITE_ADD_TEST(suite, test_cil_gen_level_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_emptysensparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_emptycat_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_nosens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_level); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_level_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangeinvalid_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_levelrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_levelrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain); SUITE_ADD_TEST(suite, test_cil_gen_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_noperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_noperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expression_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_constrain); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_constrain_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_mlsconstrain); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_mlsconstrain_neg); SUITE_ADD_TEST(suite, test_cil_fill_context); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl); SUITE_ADD_TEST(suite, test_cil_fill_context_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nouser_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_norole_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_notype_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nolowlvl_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nohighlvl_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl_nocontextlow_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl_nocontexthigh_neg); SUITE_ADD_TEST(suite, test_cil_gen_context); SUITE_ADD_TEST(suite, test_cil_gen_context_notinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_extralevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_emptycontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_doubleparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_norole_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_roleinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_nolevels_neg); // SUITE_ADD_TEST(suite, test_cil_gen_context_nosecondlevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_nouser_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_context); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_file); SUITE_ADD_TEST(suite, test_cil_gen_filecon_dir); SUITE_ADD_TEST(suite, test_cil_gen_filecon_char); SUITE_ADD_TEST(suite, test_cil_gen_filecon_block); SUITE_ADD_TEST(suite, test_cil_gen_filecon_socket); SUITE_ADD_TEST(suite, test_cil_gen_filecon_pipe); SUITE_ADD_TEST(suite, test_cil_gen_filecon_symlink); SUITE_ADD_TEST(suite, test_cil_gen_filecon_any); SUITE_ADD_TEST(suite, test_cil_gen_filecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_filecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str2null_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_classnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_class_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_filecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_filecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_udp); SUITE_ADD_TEST(suite, test_cil_gen_portcon_tcp); SUITE_ADD_TEST(suite, test_cil_gen_portcon_unknownprotocol_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange_one_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange_morethanone_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_singleport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_lowport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_highport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_str1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_str1parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_portcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_portcon_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrnodenull_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrinparens_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipanon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipanon_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmasknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmaskanon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmaskanon_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_nodecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_nodecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_typenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_typeparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_pathnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_pathparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_genfscon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_emptysecondlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_extra_nested_secondlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_missingobjects_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_secondnested_missingobjects_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_ethmissing_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_interfacemissing_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_packetmissing_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_netifcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_netifcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_pirqnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_nopirq_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_pirqrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pirqcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pirqcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_firstnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_secondnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_singleiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_noiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_iomemcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_iomemcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_firstnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_secondnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_singleioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_noioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ioportcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ioportcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_pcidevicenotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_nopcidevice_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_pcidevicerange_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pcidevicecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_anoncontext); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_xattr); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_task); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_transition); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_invalidtype_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_nofilesystem_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_filesysteminparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_emptyconparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_fsuse); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparams); SUITE_ADD_TEST(suite, test_cil_gen_macro_type); SUITE_ADD_TEST(suite, test_cil_gen_macro_role); SUITE_ADD_TEST(suite, test_cil_gen_macro_user); SUITE_ADD_TEST(suite, test_cil_gen_macro_sensitivity); SUITE_ADD_TEST(suite, test_cil_gen_macro_category); SUITE_ADD_TEST(suite, test_cil_gen_macro_catset); SUITE_ADD_TEST(suite, test_cil_gen_macro_level); SUITE_ADD_TEST(suite, test_cil_gen_macro_class); SUITE_ADD_TEST(suite, test_cil_gen_macro_classmap); SUITE_ADD_TEST(suite, test_cil_gen_macro_permset); SUITE_ADD_TEST(suite, test_cil_gen_macro_duplicate); SUITE_ADD_TEST(suite, test_cil_gen_macro_duplicate_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_unknown_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_unnamed_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_nosecondparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparam_name_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_emptyparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_paramcontainsperiod_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_nested_macro_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_call); SUITE_ADD_TEST(suite, test_cil_gen_call_noargs); SUITE_ADD_TEST(suite, test_cil_gen_call_anon); SUITE_ADD_TEST(suite, test_cil_gen_call_empty_call_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_name_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_noname_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_call); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_call_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional); SUITE_ADD_TEST(suite, test_cil_gen_optional_emptyoptional); SUITE_ADD_TEST(suite, test_cil_gen_optional_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_unnamed_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_norule_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_optional); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_optional_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap); SUITE_ADD_TEST(suite, test_cil_gen_policycap_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_policycap); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_policycap_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv4); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv4_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv6); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv6_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_noip_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ipaddr); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_extraargsnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_last_child_helper); SUITE_ADD_TEST(suite, test_cil_build_ast_last_child_helper_extraargsnull_neg); return suite; } CuSuite* CilTreeGetSuite(void) { CuSuite* suite = CuSuiteNew(); /* CilTest.c */ SUITE_ADD_TEST(suite, test_symtab_init); SUITE_ADD_TEST(suite, test_symtab_init_no_table_neg); /* test_cil.c */ SUITE_ADD_TEST(suite, test_cil_symtab_array_init); SUITE_ADD_TEST(suite, test_cil_db_init); SUITE_ADD_TEST(suite, test_cil_get_symtab_block); SUITE_ADD_TEST(suite, test_cil_get_symtab_class); SUITE_ADD_TEST(suite, test_cil_get_symtab_root); SUITE_ADD_TEST(suite, test_cil_get_symtab_flavor_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_null_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_node_null_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_parent_null_neg); /* test_cil_list.c */ SUITE_ADD_TEST(suite, test_cil_list_append_item); SUITE_ADD_TEST(suite, test_cil_list_append_item_append); SUITE_ADD_TEST(suite, test_cil_list_append_item_append_extra); SUITE_ADD_TEST(suite, test_cil_list_append_item_listnull_neg); SUITE_ADD_TEST(suite, test_cil_list_append_item_itemnull_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_prepend); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_prepend_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_listnull_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_itemnull_neg); /* test_cil_symtab.c */ SUITE_ADD_TEST(suite, test_cil_symtab_insert); /* test_cil_tree.c */ SUITE_ADD_TEST(suite, test_cil_tree_init); SUITE_ADD_TEST(suite, test_cil_tree_node_init); /* test_cil_lexer.c */ SUITE_ADD_TEST(suite, test_cil_lexer_setup); SUITE_ADD_TEST(suite, test_cil_lexer_next); /* test_cil_parser.c */ SUITE_ADD_TEST(suite, test_cil_parser); /* test_cil_fqn.c */ SUITE_ADD_TEST(suite, test_cil_qualify_name); SUITE_ADD_TEST(suite, test_cil_qualify_name_cil_flavor); /* test cil_copy_ast.c */ SUITE_ADD_TEST(suite, test_cil_copy_list); SUITE_ADD_TEST(suite, test_cil_copy_list_sublist); SUITE_ADD_TEST(suite, test_cil_copy_list_sublist_extra); SUITE_ADD_TEST(suite, test_cil_copy_list_orignull_neg); SUITE_ADD_TEST(suite, test_cil_copy_block); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_block); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_block_merge); SUITE_ADD_TEST(suite, test_cil_copy_perm); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_perm); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_perm_neg); SUITE_ADD_TEST(suite, test_cil_copy_class); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_class); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_class_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_common); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_common); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_common_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_classcommon); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_classcommon); SUITE_ADD_TEST(suite, test_cil_copy_sid); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sid); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sid_merge); SUITE_ADD_TEST(suite, test_cil_copy_sidcontext); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_copy_user); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_user); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_user_merge); SUITE_ADD_TEST(suite, test_cil_copy_role); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_role); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_role_merge); SUITE_ADD_TEST(suite, test_cil_copy_userrole); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_copy_type); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type_merge); SUITE_ADD_TEST(suite, test_cil_copy_typeattribute); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typeattribute); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typeattribute_merge); SUITE_ADD_TEST(suite, test_cil_copy_typealias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typealias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_bool); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_bool); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_bool_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_avrule); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_avrule); SUITE_ADD_TEST(suite, test_cil_copy_type_rule); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type_rule); SUITE_ADD_TEST(suite, test_cil_copy_sens); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sens); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sens_merge); SUITE_ADD_TEST(suite, test_cil_copy_sensalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sensalias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_cat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_cat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_cat_merge); SUITE_ADD_TEST(suite, test_cil_copy_catalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catalias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_senscat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_senscat); SUITE_ADD_TEST(suite, test_cil_copy_catorder); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_copy_dominance); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_dominance); SUITE_ADD_TEST(suite, test_cil_copy_level); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_level); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_level_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_fill_level); SUITE_ADD_TEST(suite, test_cil_copy_context); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_context); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_context_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_netifcon); SUITE_ADD_TEST(suite, test_cil_copy_netifcon_nested); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_netifcon); SUITE_ADD_TEST(suite, test_cil_copy_fill_context); SUITE_ADD_TEST(suite, test_cil_copy_fill_context_anonrange); SUITE_ADD_TEST(suite, test_cil_copy_call); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_call); SUITE_ADD_TEST(suite, test_cil_copy_optional); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_optional); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_optional_merge); SUITE_ADD_TEST(suite, test_cil_copy_nodecon); SUITE_ADD_TEST(suite, test_cil_copy_nodecon_anon); SUITE_ADD_TEST(suite, test_cil_copy_fill_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_ipaddr_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_conditional); SUITE_ADD_TEST(suite, test_cil_copy_boolif); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_copy_constrain); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_mlsconstrain); //SUITE_ADD_TEST(suite, test_cil_copy_ast); //SUITE_ADD_TEST(suite, test_cil_copy_ast_neg); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_orignull_neg); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_extraargsnull_neg); /* test_post.c */ SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_not_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_b_not_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_type_atype_greater_btype); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_type_btype_greater_atype); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_stemlen_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_stemlen_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_atypestr_greater_btypestr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_btypestr_greater_atypestr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_apathstr_greater_bpathstr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_bpathstr_greater_apathstr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_lessthan_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_lessthan_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_type_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_type_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_fsstr_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_fsstr_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_equal); return suite; } CuSuite* CilTestFullCil(void) { CuSuite* suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_min_policy); SUITE_ADD_TEST(suite, test_integration); return suite; } libsepol/cil/test/unit/CilTest.h0100644 0000000 0000000 00000003550 13756670065 015665 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CILTEST_H_ #define CILTEST_H_ #include "../../src/cil_tree.h" // TODO Check more in the data structures struct cil_file_data { char *buffer; uint32_t file_size; }; void set_cil_file_data(struct cil_file_data **); void gen_test_tree(struct cil_tree **, char **); #endif libsepol/cil/test/unit/CuTest.c0100644 0000000 0000000 00000021513 13756670065 015517 0ustar000000000 0000000 /* * Copyright (c) 2003 Asim Jalis * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. */ #include #include #include #include #include #include #include "CuTest.h" /*-------------------------------------------------------------------------* * CuStr *-------------------------------------------------------------------------*/ char* CuStrAlloc(int size) { char* newStr = (char*) malloc( sizeof(char) * (size) ); return newStr; } char* CuStrCopy(const char* old) { int len = strlen(old); char* newStr = CuStrAlloc(len + 1); strcpy(newStr, old); return newStr; } /*-------------------------------------------------------------------------* * CuString *-------------------------------------------------------------------------*/ void CuStringInit(CuString* str) { str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; } CuString* CuStringNew(void) { CuString* str = (CuString*) malloc(sizeof(CuString)); str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; return str; } void CuStringDelete(CuString *str) { if (!str) return; free(str->buffer); free(str); } void CuStringResize(CuString* str, int newSize) { str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); str->size = newSize; } void CuStringAppend(CuString* str, const char* text) { int length; if (text == NULL) { text = "NULL"; } length = strlen(text); if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); str->length += length; strcat(str->buffer, text); } void CuStringAppendChar(CuString* str, char ch) { char text[2]; text[0] = ch; text[1] = '\0'; CuStringAppend(str, text); } __attribute__ ((format (printf, 2, 3))) void CuStringAppendFormat(CuString* str, const char* format, ...) { va_list argp; char buf[HUGE_STRING_LEN]; va_start(argp, format); vsprintf(buf, format, argp); va_end(argp); CuStringAppend(str, buf); } void CuStringInsert(CuString* str, const char* text, int pos) { int length = strlen(text); if (pos > str->length) pos = str->length; if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); str->length += length; memcpy(str->buffer + pos, text, length); } /*-------------------------------------------------------------------------* * CuTest *-------------------------------------------------------------------------*/ void CuTestInit(CuTest* t, const char* name, TestFunction function) { t->name = CuStrCopy(name); t->failed = 0; t->ran = 0; t->message = NULL; t->function = function; t->jumpBuf = NULL; } CuTest* CuTestNew(const char* name, TestFunction function) { CuTest* tc = CU_ALLOC(CuTest); CuTestInit(tc, name, function); return tc; } void CuTestDelete(CuTest *t) { if (!t) return; free(t->name); free(t); } void CuTestRun(CuTest* tc) { jmp_buf buf; tc->jumpBuf = &buf; if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } tc->jumpBuf = 0; } static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) { char buf[HUGE_STRING_LEN]; sprintf(buf, "%s:%d: ", file, line); CuStringInsert(string, buf, 0); tc->failed = 1; tc->message = string->buffer; if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) { CuString string; CuStringInit(&string); if (message2 != NULL) { CuStringAppend(&string, message2); CuStringAppend(&string, ": "); } CuStringAppend(&string, message); CuFailInternal(tc, file, line, &string); } void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) { if (condition) return; CuFail_Line(tc, file, line, NULL, message); } void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { CuString string; if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) { return; } CuStringInit(&string); if (message != NULL) { CuStringAppend(&string, message); CuStringAppend(&string, ": "); } CuStringAppend(&string, "expected <"); CuStringAppend(&string, expected); CuStringAppend(&string, "> but was <"); CuStringAppend(&string, actual); CuStringAppend(&string, ">"); CuFailInternal(tc, file, line, &string); } void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%d> but was <%d>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) { char buf[STRING_MAX]; if (fabs(expected - actual) <= delta) return; sprintf(buf, "expected <%f> but was <%f>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); CuFail_Line(tc, file, line, message, buf); } /*-------------------------------------------------------------------------* * CuSuite *-------------------------------------------------------------------------*/ void CuSuiteInit(CuSuite* testSuite) { testSuite->count = 0; testSuite->failCount = 0; memset(testSuite->list, 0, sizeof(testSuite->list)); } CuSuite* CuSuiteNew(void) { CuSuite* testSuite = CU_ALLOC(CuSuite); CuSuiteInit(testSuite); return testSuite; } void CuSuiteDelete(CuSuite *testSuite) { unsigned int n; for (n=0; n < MAX_TEST_CASES; n++) { if (testSuite->list[n]) { CuTestDelete(testSuite->list[n]); } } free(testSuite); } void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) { assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { int i; for (i = 0 ; i < testSuite2->count ; ++i) { CuTest* testCase = testSuite2->list[i]; CuSuiteAdd(testSuite, testCase); } } void CuSuiteRun(CuSuite* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuTestRun(testCase); if (testCase->failed) { testSuite->failCount += 1; } } } void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuStringAppend(summary, testCase->failed ? "F" : "."); } CuStringAppend(summary, "\n\n"); } void CuSuiteDetails(CuSuite* testSuite, CuString* details) { int i; int failCount = 0; if (testSuite->failCount == 0) { int passCount = testSuite->count - testSuite->failCount; const char* testWord = passCount == 1 ? "test" : "tests"; CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); } else { if (testSuite->failCount == 1) CuStringAppend(details, "There was 1 failure:\n"); else CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->failed) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } CuStringAppend(details, "\n!!!FAILURES!!!\n"); CuStringAppendFormat(details, "Runs: %d ", testSuite->count); CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); } } libsepol/cil/test/unit/CuTest.h0100644 0000000 0000000 00000011614 13756670065 015525 0ustar000000000 0000000 /* * Copyright (c) 2003 Asim Jalis * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. */ #ifndef CU_TEST_H #define CU_TEST_H #include #include #define CUTEST_VERSION "CuTest 1.5" /* CuString */ char* CuStrAlloc(int size); char* CuStrCopy(const char* old); #define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) #define HUGE_STRING_LEN 8192 #define STRING_MAX 256 #define STRING_INC 256 typedef struct { int length; int size; char* buffer; } CuString; void CuStringInit(CuString* str); CuString* CuStringNew(void); void CuStringRead(CuString* str, const char* path); void CuStringAppend(CuString* str, const char* text); void CuStringAppendChar(CuString* str, char ch); void CuStringAppendFormat(CuString* str, const char* format, ...); void CuStringInsert(CuString* str, const char* text, int pos); void CuStringResize(CuString* str, int newSize); void CuStringDelete(CuString* str); /* CuTest */ typedef struct CuTest CuTest; typedef void (*TestFunction)(CuTest *); struct CuTest { char* name; TestFunction function; int failed; int ran; const char* message; jmp_buf *jumpBuf; }; void CuTestInit(CuTest* t, const char* name, TestFunction function); CuTest* CuTestNew(const char* name, TestFunction function); void CuTestRun(CuTest* tc); void CuTestDelete(CuTest *t); /* Internal versions of assert functions -- use the public versions */ void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta); void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual); /* public assert functions */ #define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) #define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) #define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) #define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) #define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) #define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) #define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) /* CuSuite */ #define MAX_TEST_CASES 1024 #define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) typedef struct { int count; CuTest* list[MAX_TEST_CASES]; int failCount; } CuSuite; void CuSuiteInit(CuSuite* testSuite); CuSuite* CuSuiteNew(void); void CuSuiteDelete(CuSuite *testSuite); void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); void CuSuiteRun(CuSuite* testSuite); void CuSuiteSummary(CuSuite* testSuite, CuString* summary); void CuSuiteDetails(CuSuite* testSuite, CuString* details); #endif /* CU_TEST_H */ libsepol/cil/test/unit/test_cil.c0100644 0000000 0000000 00000012531 13756670065 016116 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil.h" #include "../../src/cil_internal.h" #include "../../src/cil_tree.h" void test_cil_symtab_array_init(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); cil_symtab_array_init(test_new_db->symtab, cil_sym_sizes[CIL_SYM_ARRAY_ROOT]); CuAssertPtrNotNull(tc, test_new_db->symtab); free(test_new_db); } void test_cil_db_init(CuTest *tc) { struct cil_db *test_db; cil_db_init(&test_db); CuAssertPtrNotNull(tc, test_db->ast); CuAssertPtrNotNull(tc, test_db->symtab); CuAssertPtrNotNull(tc, test_db->symtab); } // TODO: Reach SEPOL_ERR return in cil_db_init ( currently can't produce a method to do so ) void test_cil_get_symtab_block(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_BLOCK; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_class(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_CLASS; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_root(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_ROOT; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_flavor_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = 1234567; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } void test_cil_get_symtab_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } void test_cil_get_symtab_node_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_get_symtab(test_db, test_ast_node, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); CuAssertPtrEquals(tc, test_ast_node, NULL); } void test_cil_get_symtab_parent_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } libsepol/cil/test/unit/test_cil.h0100644 0000000 0000000 00000004130 13756670065 016117 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_H_ #define TEST_CIL_H_ #include "CuTest.h" void test_cil_symtab_array_init(CuTest *); void test_cil_symtab_array_init_null_symtab_neg(CuTest *); void test_cil_db_init(CuTest *); void test_cil_get_symtab_block(CuTest *); void test_cil_get_symtab_class(CuTest *); void test_cil_get_symtab_root(CuTest *); void test_cil_get_symtab_flavor_neg(CuTest *); void test_cil_get_symtab_null_neg(CuTest *); void test_cil_get_symtab_node_null_neg(CuTest *); void test_cil_get_symtab_parent_null_neg(CuTest *); #endif libsepol/cil/test/unit/test_cil_build_ast.c0100644 0000000 0000000 00002156456 13756670065 020165 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_build_ast.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_tree.h" int __cil_build_ast_node_helper(struct cil_tree_node *, uint32_t *, void *); int __cil_build_ast_last_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *); //int __cil_build_constrain_tree(struct cil_tree_node *parse_current, struct cil_tree_node *expr_root); struct cil_args_build { struct cil_tree_node *ast; struct cil_db *db; struct cil_tree_node *macro; struct cil_tree_node *tifstack; }; struct cil_args_build *gen_build_args(struct cil_tree_node *node, struct cil_db *db, struct cil_tree_node * macro, struct cil_tree_node *tifstack) { struct cil_args_build *args = cil_malloc(sizeof(*args)); args->ast = node; args->db = db; args->macro = macro; args->tifstack = tifstack; return args; } // First seen in cil_gen_common void test_cil_parse_to_list(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); test_current = test_current->next->next->next->cl_head->next->cl_head; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_OK, rc); cil_destroy_avrule(test_avrule); } void test_cil_parse_to_list_currnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); test_current = NULL; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_destroy_avrule(test_avrule); } void test_cil_parse_to_list_listnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); test_current = test_current->next->next->next->cl_head->next->cl_head; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_destroy_avrule(test_avrule); } void test_cil_set_to_list(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l = NULL; struct cil_list *sub_list = NULL; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); int rc = cil_set_to_list(test_tree->root->cl_head, cil_l, 1); sub_list = (struct cil_list *)cil_l->head->next->next->data; CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, "foo1", (char*)cil_l->head->data); CuAssertStrEquals(tc, "foo2", (char*)cil_l->head->next->data); CuAssertStrEquals(tc, "foo3", (char*)sub_list->head->data); } void test_cil_set_to_list_tree_node_null_neg(CuTest *tc) { struct cil_list *cil_l = NULL; int rc = cil_set_to_list(NULL, cil_l, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_set_to_list_cl_head_null_neg(CuTest *tc) { char *line[] = {"(", "foo", "bar", ")", NULL}; struct cil_list *cil_l; struct cil_tree *test_tree = NULL; cil_list_init(&cil_l); gen_test_tree(&test_tree, line); test_tree->root->cl_head = NULL; int rc = cil_set_to_list(test_tree->root, cil_l, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_set_to_list_listnull_neg(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "foo3", ")", NULL}; struct cil_tree *test_tree = NULL; gen_test_tree(&test_tree, line); int rc = cil_set_to_list(test_tree->root, NULL, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_block*)test_ast_node->data)->is_abstract, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BLOCK); } void test_cil_gen_block_justblock_neg(CuTest *tc) { char *line[] = {"(", "block", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_noname_neg(CuTest *tc) { char *line[] = {"(", "block", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_dbnull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_treenull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_tree->root->cl_head->cl_head = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_nodenull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_nodeparentnull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_destroy_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); cil_destroy_block((struct cil_block*)test_ast_node->data); CuAssertPtrEquals(tc, NULL,test_ast_node->data); } void test_cil_gen_blockinherit(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_blockinherit_namelist_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_namenull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_extra_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_dbnull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_astnull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; test_ast_node->parent = new_tree_node; test_ast_node->line = 1; int rc = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); int rc1 = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next, test_ast_node); int rc2 = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next->next, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc1); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_gen_perm_dbnull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; test_current_perm = test_tree->root->cl_head->cl_head->next->next->cl_head; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; test_new_ast->line = test_current_perm->line; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_currnull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_current_perm = NULL; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_astnull_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; int rc = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_nodenull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_current_perm = test_tree->root->cl_head->cl_head->next->next->cl_head; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; test_new_ast->line = test_current_perm->line; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_permset_noname_neg(CuTest *tc) { char *line[] = {"(", "permissionset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "(", "foo", ")", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_noperms_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_extra_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_astnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_nodes(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_perm_nodes_failgen_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); cil_symtab_destroy(&test_cls->perms); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_ENOMEM, rc); } void test_cil_gen_perm_nodes_inval_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "(", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_permset_sublist_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset_startpermnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset_permsetnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset = NULL; int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_in_blockstrnull_neg(CuTest *tc) { char *line[] = {"(", "in", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_extra_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_dbnull_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_astnull_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->cl_tail); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_CLASS); } void test_cil_gen_class_noname_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_nodenull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_dbnull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_currnull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_tree->root->cl_head->cl_head = NULL; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noclass_neg(CuTest *tc) { char *line[] = {"(", "test", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noclassname_neg(CuTest *tc) { char *line[] = {"(", "class", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_namesublist_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noperms(CuTest *tc) { char *line[] = {"(", "class", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_class_permsnotinlist_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "read", "write", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_extrapermlist_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", "(", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_listinlist_neg(CuTest *tc) { char *line[] = {"(", "class", "test", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_anonperms(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_classpermset_anonperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", "(", "extra", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_namedperms(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "perms", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_classpermset_extra_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_emptypermslist_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_noperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_noclass_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_classnodenull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_cpsnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps = NULL; int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classpermset_noname_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "(", "foo", ")", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_noclass_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_noperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "char", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_extra_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_astnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_classmap *map = NULL; cil_classmap_init(&map); test_ast_node->flavor = CIL_CLASSMAP; test_ast_node->data = map; struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->next->next->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->next->next->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmap_perm_dupeperm_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->next->next->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->next->next->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_EEXIST, rc); } void test_cil_gen_classmap_perm_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->path; test_db = NULL; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm_currnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a = NULL; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmap_extra_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_noname_neg(CuTest *tc) { char *line[] = {"(", "classmap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_anonpermset(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmapping_anonpermset_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_namedpermset(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmapping_noclassmapname_neg(CuTest *tc) { char *line[] = {"(", "classmapping", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_noclassmapperm_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_nopermissionsets_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_COMMON); } void test_cil_gen_common_dbnull_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_astnull_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_noname_neg(CuTest *tc) { char *line[] = {"(", "common", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_twoperms_neg(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "write", ")", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_permsublist_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_noperms_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_sid_noname_neg(CuTest *tc) { char *line[] = {"(", "sid", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "sid", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_extra_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_astnull_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SIDCONTEXT); } void test_cil_gen_sidcontext_namedcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "something", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SIDCONTEXT); } void test_cil_gen_sidcontext_halfcontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_noname_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_empty_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_nocontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_dblname_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "test2", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_pcurrnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_astnodenull_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE); } void test_cil_gen_type_dbnull_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_astnull_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_extra_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", "bar," ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPEATTRIBUTE); } void test_cil_gen_typeattribute_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_astnull_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_extra_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "foo", "bar," ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_typebounds_notype1_neg(CuTest *tc) { char *line[] = {"(", "typebounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_type1inparens_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "(", "type_a", ")", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_notype2_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_type2inparens_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "(", "type_b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_extra_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_typepermissive_noname_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "(", "type_a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_extra_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_astnull_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nametypetransition_strinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "(", "str", ")", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nostr_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_srcinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "(", "foo", ")", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nosrc_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_tgtinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "(", "bar", ")", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_notgt_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_classinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "(", "file", ")", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_noclass_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_destinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "(", "foobar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nodest_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_extra_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_dbnull_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_astnull_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_namedtransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "namedtrans", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_low_l(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "(", "s0", "(", "c0", ")", ")", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_low_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "(", "s0", "(", ")", ")", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_anon_high_l(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_high_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "(", "s0", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_dbnull_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_astnull_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nofirsttype_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_firsttype_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "(", "type_a_t", ")", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nosecondtype_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_secondtype_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "(", "type_b_t", ")", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_noclass_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_class_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "(", "class", ")", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nolevel_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nolevel_h_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_extra_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_and(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_or(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_xor(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_not(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", "foo", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_not_noexpr_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_not_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_eq(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_neq(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "neq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_nested(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "(","neq", "foo", "bar", ")", "(", "eq", "baz", "boo", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_nested_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(","neq", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_nested_emptyargs_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "(", ")", "(", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_nested_missingoperator_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "(","foo", "bar", ")", "(", "eq", "baz", "boo", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_arg1null_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_arg2null_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_extraarg_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", "bar", "extra", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_currnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_stacknull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_multiplebools_true(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_multiplebools_false(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "false", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_multiplebools_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_true(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_false(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nested(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_nested_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_extra_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "(", "or", "foo", "bar", ")", "baz", "beef", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_extra_parens_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nocond(CuTest *tc) { char *line[] = {"(", "booleanif", "baz", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "**", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_dbnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_astnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nocond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_notruelist_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_empty_cond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_multiplebools_true(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_multiplebools_false(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "false", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_multiplebools_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_true(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_false(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_nocond(CuTest *tc) { char *line[] = {"(", "tunableif", "baz", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_nested(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_nested_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_extra_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", "beef", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_extra_parens_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "**", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_dbnull_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_astnull_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_nocond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_notruelist_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_true(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_condblock_false(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_condblock_dbnull_neg(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_astnull_neg(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_nocond_neg(CuTest *tc) { char *line[] = {"(", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_extra_neg(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", "Extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_typealias*)test_ast_node->data)->type_str, test_tree->root->cl_head->cl_head->next->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPEALIAS); } void test_cil_gen_typealias_incomplete_neg(CuTest *tc) { char *line[] = {"(", "typealias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_incomplete_neg2(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_extratype_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "foo", "extra_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_astnull_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "test_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_and_two_types(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "and", "test_t", "test2_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_not(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "notypes_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_exclude_attr(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "attr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_exclude_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_astnull_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_noname_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "(", "filetypes", ")", "(", "test_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_emptylists_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_listinparens_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "(", "test_t", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_extra_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "test_t", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userbounds(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_gen_userbounds_notype1_neg(CuTest *tc) { char *line[] = {"(", "userbounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_type1_inparens_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "(", "user1", ")", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_notype2_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_type2_inparens_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "(", "user2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_extra_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_role(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLE); } void test_cil_gen_role_dbnull_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_astnull_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_extrarole_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", "extra_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_noname_neg(CuTest *tc) { char *line[] = {"(", "role", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLETRANSITION); } void test_cil_gen_roletransition_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_astnull_neg (CuTest *tc) { char *line[] = {"(", "roletransition" "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_srcnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_resultnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next->next->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_extra_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_true(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 1); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BOOL); } void test_cil_gen_bool_tunable_true(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_TUNABLE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 1); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TUNABLE); } void test_cil_gen_bool_false(CuTest *tc) { char *line[] = {"(", "boolean", "bar", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BOOL); } void test_cil_gen_bool_tunable_false(CuTest *tc) { char *line[] = {"(", "tunable", "bar", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_TUNABLE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TUNABLE); } void test_cil_gen_bool_none_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_dbnull_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_astnull_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_notbool_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_boolname_neg(CuTest *tc) { char *line[] = {"(", "boolean", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_extraname_false_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "false", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_extraname_true_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1type(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1t1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "t1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t2type(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t2", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_t2t2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t2", "t2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1role(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1r1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_r2role(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r2", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r2r2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r2", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1t2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "t2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_r1r2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1r2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1u2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "u2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1user(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1u1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "u1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_u2user(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u2", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u2u2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u2", "u2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l2h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l1h1(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l1h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1l2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "l1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_CONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_CONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h2", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", "neq", "l2", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_not_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not_emptyparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not_extraparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", "neq", "l2", "h2", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "neq", "l1", "l2", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_or_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "neq", "l1", "l2", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_and_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_dom_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_domby_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_currnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_stacknull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_operatorinparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "(", "eq", ")", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incorrectcall_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next->cl_head->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", "sysadm_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_roleallow*)test_ast_node->data)->src_str, test_current->next->data); CuAssertStrEquals(tc, ((struct cil_roleallow*)test_ast_node->data)->tgt_str, test_current->next->next->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLEALLOW); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_roleallow_dbnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_roleallow(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_astnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_srcnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_extra_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rolebounds(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_gen_rolebounds_norole1_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_role1_inparens_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "(", "role1", ")", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_norole2_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_role2_inparens_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "(", "role2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_extra_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->src_str, test_current->next->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->tgt_str, test_current->next->next->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->classpermset->class_str, test_current->next->next->next->cl_head->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_AVRULE); CuAssertPtrNotNull(tc, ((struct cil_avrule*)test_ast_node->data)->classpermset->permset->perms_list_str); struct cil_list_item *test_list = ((struct cil_avrule*)test_ast_node->data)->classpermset->permset->perms_list_str->head; test_current = test_current->next->next->next->cl_head->next->cl_head; while(test_list != NULL) { CuAssertIntEquals(tc, test_list->flavor, CIL_AST_STR); CuAssertStrEquals(tc, test_list->data, test_current->data ); test_list = test_list->next; test_current = test_current->next; } } void test_cil_gen_avrule_permset(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "permset", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_avrule_permset_anon(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_avrule_extra_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "permset", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourceparens(CuTest *tc) { char *line[] = {"(", "allow", "(", "test", ")", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourceemptyparen_neg(CuTest *tc) { char *line[] = {"(", "allow", "(", ")", "bar", "file", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetparens(CuTest *tc) { char *line[] = {"(", "allow", "test", "(", "foo", ")", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetemptyparen_neg(CuTest *tc) { char *line[] = {"(", "allow", "bar", "(", ")", "file", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_astnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourcedomainnull_neg(CuTest *tc) { char *line[] = {"(", "allow", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetdomainnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_objectclassnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_permsnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", "(", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_twolists_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "write", ")", "(", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_transition_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_astnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_objnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_extra_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_change_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_astnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_objnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_extra_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_member_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_astnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_objnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_extra_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_USER, test_ast_node->flavor); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertPtrEquals(tc, test_ast_node, ((struct cil_symtab_datum*)test_ast_node->data)->node); CuAssertStrEquals(tc, test_tree->root->cl_head->cl_head->next->data, ((struct cil_symtab_datum*)test_ast_node->data)->name); } void test_cil_gen_user_dbnull_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_astnull_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_nouser_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_xsinfo_neg(CuTest *tc) { char *line[] = {"(", "user", "sysadm", "xsinfo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "lvl_l", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userlevel_anon_level(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userlevel_anon_level_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_usernull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_userrange_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "(", "user", ")", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_levelnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_levelrangeempty_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_extra_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "level", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_astnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_named(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrange_anon(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrange_usernull_neg(CuTest *tc) { char *line[] = {"(", "userrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonuser_neg(CuTest *tc) { char *line[] = {"(", "userrange", "(", "user_u", ")", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_rangenamenull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonrangeinvalid_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonrangeempty_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_extra_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", "high", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SENS); } void test_cil_gen_sensitivity_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sensitivity(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_senslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "(", "s0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_extra_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_sensalias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sensalias(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init (&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_senslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "(", "s0", "s1", ")", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_aliasnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_aliaslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "(", "alias", "alias2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_extra_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_category_dbnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_astnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_currnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_catnull_neg(CuTest *tc){ char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_catlist_neg(CuTest *tc){ char *line[] = {"(", "category", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_extra_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_currnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_namenull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_setnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_namelist_neg(CuTest *tc) { //This should fail before gen_node call - additional syntax checks are needed char *line[] = {"(", "categoryset", "(", "somecats", ")", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_notset_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } // TODO: This doesn't actually test failure of gen_node void test_cil_gen_catset_nodefail_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_settolistfail_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catalias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_currnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_catnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_aliasnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catrange_noname_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_norange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_emptyrange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_extrarange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_roletype_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_dbnull_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_astnull_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_empty_neg(CuTest *tc) { char *line[] = {"(", "roletype", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_rolelist_neg(CuTest *tc) { char *line[] = {"(", "roletype", "(", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } // TODO // Not sure this is actually testing roletype // I think this will just test that type is null void test_cil_gen_roletype_roletype_sublist_neg(CuTest *tc) { char *line[] = {"(", "(", "roletype", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_typelist_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "(", "admin_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrole_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_astnull_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_empty_neg(CuTest *tc) { char *line[] = {"(", "userrole", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_userlist_neg(CuTest *tc) { char *line[] = {"(", "userrole", "(", "staff_u", ")", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } //TODO: see above void test_cil_gen_userrole_userrole_sublist_neg(CuTest *tc) { char *line[] = {"(", "(", "userrole", "staff_u", ")", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_rolelist_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "(", "staff_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classcommon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_astnull_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_missingclassname_neg(CuTest *tc) { char *line[] = {"(", "classcommon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_noperms_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_extraperms_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catorder_dbnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_currnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_astnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_missingcats_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_nosublist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "c0", "c255", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_nestedcat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "(", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_dominance_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_nosensitivities_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_nosublist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "s0", "s2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_senscat_nosublist(CuTest *tc) { char *line[] = {"(", "sensitivitycategory", "s1", "c0", "c255", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_senscat_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_nosensitivities_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_sublist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_nocat_neg(CuTest *tc) { char *line[] = {"(", "sensitivitycategory", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_level_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level_levelnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level = NULL; int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level_nocat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_level_emptycat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_level_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "level", "(", "low", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_emptysensparens_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_extra_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c0", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_emptycat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_noname_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_nosens_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_levelrange_rangeinvalid_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_namenull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_rangenull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_rangeempty_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_extra_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dne", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_noclass_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_noperm_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_noclass_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_noperm_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expression_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_dbnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_astnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_context_unnamedlvl(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "(", "s0", ")", "(", "s0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_context_nocontext_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context = NULL; int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nouser_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_norole_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_notype_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nolowlvl_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nohighlvl_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "(", "low", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_unnamedlvl_nocontextlow_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "(", "s0", "(", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_unnamedlvl_nocontexthigh_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "low", "(", "s0", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_context_notinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_extralevel_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_emptycontext_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_extra_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", "(", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_doubleparen_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "(", "system_u", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_norole_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_roleinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "(", "role_r", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_notype_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "(", "type_t", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nolevels_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nosecondlevel_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "type_t", "(", "low", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_noname_neg(CuTest *tc) { char *line[] = {"(", "context", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nouser_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_dbnull_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "s0", ")", "(", "s0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_astnull_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "system_u", "object_r", "node_lo_t", "(", "s0", ")", "(", "s0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_dir(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "dir", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_file(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_char(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "char", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_block(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "block", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_socket(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "socket", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_pipe(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "pipe", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_symlink(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "symlink", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_any(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "any", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "dne", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_anon_context(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str1null_neg(CuTest *tc) { char *line[] = {"(", "filecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str1_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "(", "root", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str2null_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str2_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "(", "path", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_classnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_class_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "(", "file", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_context_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_extra_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_udp(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_tcp(CuTest *tc) { char *line[] = {"(", "portcon", "tcp", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_unknownprotocol_neg(CuTest *tc) { char *line[] = {"(", "portcon", "unknown", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_anon_context(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_portrange(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "25", "75", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_portrange_one_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_portrange_morethanone_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_singleport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "foo", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_lowport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "foo", "90", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_highport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "80", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_str1null_neg(CuTest *tc) { char *line[] = {"(", "portcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_str1parens_neg(CuTest *tc) { char *line[] = {"(", "portcon", "(", "80", ")", "port", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_portnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "port", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_context_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_extra_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_ipaddr_addrnodenull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(NULL, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_addrnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); nodecon->addr = NULL; int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_addrinparens_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "(", "192.168.1.1", ")", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_extra_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", "extra", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_anon_context(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_ipnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_ipanon(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_ipanon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_netmasknull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_netmaskanon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "(", "255.255.255.4", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_netmaskanon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "(", "str0", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_context_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_extra_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "type_t", "(", "low", "high", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_genfscon_anon_context(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_genfscon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_astnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_typenull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_typeparens_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "(", "type", ")", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_pathnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_pathparens_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "(", "path", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_context_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_extra_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_netifcon_nested(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_netifcon_nested_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "(", "eth1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_emptysecondlist_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_extra_nested_secondlist_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "extra", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_missingobjects_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_secondnested_missingobjects_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_ethmissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_interfacemissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_packetmissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_pirqcon_pirqnotint_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_nopirq_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_pirqrange_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_extra_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_iomemcon_iomemrange(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_iomemcon_iomemrange_firstnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "foo", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_secondnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_empty_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_singleiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "2", "3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_noiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_extra_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ioportcon_ioportrange(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ioportcon_ioportrange_firstnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "foo", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_secondnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_empty_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_singleioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "2", "3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_noioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_extra_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_pcidevicecon_pcidevicenotint_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_nopcidevice_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_pcidevicerange_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_extra_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_anoncontext(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", "system_u", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_xattr(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_task(CuTest *tc) { char *line[] = {"(", "fsuse", "task", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_transition(CuTest *tc) { char *line[] = {"(", "fsuse", "trans", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_invalidtype_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "foo", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_notype_neg(CuTest *tc) { char *line[] = {"(", "fsuse", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "(", "xattr", ")", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_nofilesystem_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_filesysteminparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "(", "ext3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_nocontext_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_emptyconparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_extra_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_dbnull_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_astnull_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparams(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_type(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_role(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_user(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_sensitivity(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_category(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_catset(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "categoryset", "a", ")", ")", "(", "categoryset", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_level(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "level", "a", ")", ")", "(", "level", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_class(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_classmap(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmap", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_permset(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "foo", "bar", "baz", "a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_duplicate(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a",")", "(", "class", "x", ")", ")", "(", "class", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_duplicate_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a",")", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read," ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_unknown_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_dbnull_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_astnull_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node = NULL; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_unnamed_neg(CuTest *tc) { char *line[] = {"(", "macro", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_nosecondparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparam_name_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_emptyparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_paramcontainsperiod_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a.", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_noargs(CuTest *tc) { char *line[] = {"(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_anon(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_empty_call_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_dbnull_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_astnull_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_name_inparens_neg(CuTest *tc) { char *line[] = {"(", "call", "(", "mm", ")", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_noname_neg(CuTest *tc) { char *line[] = {"(", "call", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_optional_dbnull_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_astnull_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_unnamed_neg(CuTest *tc) { char *line[] = {"(", "optional", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_extra_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "optional", "(", "opt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_emptyoptional(CuTest *tc) { char *line[] = {"(", "optional", "opt", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_optional_norule_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "open_perms", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_policycap_noname_neg(CuTest *tc) { char *line[] = {"(", "policycap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "policycap", "(", "pol", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_extra_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_dbnull_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_astnull_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipv4(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ipaddr_ipv4_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", ".168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipv6(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ipaddr_ipv6_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "2001:0db8:85a3:0000:0000:8a2e:0370:::7334", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_noname_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "(", "ip", ")", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_noip_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipinparens_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "(", "192.168.1.1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_extra_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_dbnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_astnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } /* cil_build_ast test cases */ void test_cil_build_ast(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_dbnull_neg(CuTest *tc) { char *line[] = {"(", "test", "\"qstring\"", ")", ";comment", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *null_db = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(null_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_astnull_neg(CuTest *tc) { char *line[] = {"(", "test", "\"qstring\"", ")", ";comment", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_suberr_neg(CuTest *tc) { char *line[] = {"(", "block", "test", "(", "block", "(", "type", "log", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_treenull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_block(CuTest *tc) { char *line[] = {"(", "block", "test", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_block_neg(CuTest *tc) { char *line[] = {"(", "block", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_blockinherit(CuTest *tc) { char *line[] = {"(", "blockinherit", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_blockinherit_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_TREE_SKIP_NEXT, finished); } void test_cil_build_ast_node_helper_permset_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_in(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_in_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_class_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classpermset(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_TREE_SKIP_NEXT, finished); } void test_cil_build_ast_node_helper_classpermset_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classmap(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_classmap_neg(CuTest *tc) { char *line[] = {"(", "classmap", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classmapping(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_classmapping_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_common_neg(CuTest *tc) { char *line[] = {"(", "common", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_sid_neg(CuTest *tc) { char *line[] = {"(", "sid", "(", "blah", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_sidcontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "(", "blah", "blah", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_user(CuTest *tc) { char *line[] = {"(", "user", "jimmypage", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo", "bar", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userlevel(CuTest *tc) { char *line[] = {"(", "userlevel", "johnpauljones", "level", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_userlevel_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "johnpauljones", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userrange(CuTest *tc) { char *line[] = {"(", "userrange", "johnpauljones", "range", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_userrange_neg(CuTest *tc) { char *line[] = {"(", "userrange", "johnpauljones", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_neg(CuTest *tc) { char *line[] = {"(", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_attribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_attribute_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typebounds(CuTest *tc) { char *line[] = {"(", "typebounds", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typebounds_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typepermissive(CuTest *tc) { char *line[] = {"(", "typepermissive", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_nametypetransition(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_nametypetransition_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rangetransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a", "type_b", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_rangetransition_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_boolif_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "*&", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_true(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_true_neg(CuTest *tc) { char *line[] = {"(", "true", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_false(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_false_neg(CuTest *tc) { char *line[] = {"(", "false", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_tunif(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "*&", "foo", "bar", ")", "(", "allow", "foo", "bar", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typealias_notype_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattribute_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", ".fail.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "and", "test_t", "test2_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_typeattributeset_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userbounds(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userbounds_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_role(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_role_neg(CuTest *tc) { char *line[] = {"(", "role", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletransition(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletransition_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roleallow(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", "sysadm_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roleallow_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rolebounds(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rolebounds_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_allow(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_allow_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_auditallow(CuTest *tc) { char *line[] = {"(", "auditallow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_auditallow_neg(CuTest *tc) { char *line[] = {"(", "auditallow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_dontaudit(CuTest *tc) { char *line[] = {"(", "dontaudit", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_dontaudit_neg(CuTest *tc) { char *line[] = {"(", "dontaudit", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_neverallow(CuTest *tc) { char *line[] = {"(", "neverallow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_neverallow_neg(CuTest *tc) { char *line[] = {"(", "neverallow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_transition(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_transition_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_change(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_change_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_member(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_member_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_tunable(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_tunable_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensitivity(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensitivity_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensalias_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_category(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_category_neg(CuTest *tc) { char *line[] = {"(", "category", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catset_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catorder_neg(CuTest *tc) { char *line[] = {"(", "categoryorder", "c0", "c1", "c2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catalias_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catrange(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catrange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletype(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_roletype_neg(CuTest *tc) { char *line[] = {"(", "roletype", "(", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_userrole_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "(", "staff_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "foo", "foo", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_classcommon_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "staff_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_senscat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_levelrange(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_levelrange_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_constrain(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_mlsconstrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_mlsconstrain_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_context(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_context_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_filecon(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_filecon_neg(CuTest *tc) { char *line[] = {"(", "filecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_portcon(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_portcon_neg(CuTest *tc) { char *line[] = {"(", "portcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_nodecon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_genfscon(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_genfscon_neg(CuTest *tc) { char *line[] = {"(", "genfscon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_netifcon_neg(CuTest *tc) { char *line[] = {"(", "netifcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_pirqcon(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_pirqcon_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_iomemcon(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_iomemcon_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_ioportcon(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_ioportcon_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_pcidevicecon(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_pcidevicecon_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_fsuse(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_fsuse_neg(CuTest *tc) { char *line[] = {"(", "fsuse", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_macro_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_macro_nested_macro_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_macro *macro; cil_macro_init(¯o); struct cil_tree_node *macronode; cil_tree_node_init(¯onode); macronode->data = macro; macronode->flavor = CIL_MACRO; uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, macronode, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_db_destroy(&test_db); cil_destroy_macro(macro); } void test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_macro *macro; cil_macro_init(¯o); struct cil_tree_node *macronode; cil_tree_node_init(¯onode); macronode->data = macro; macronode->flavor = CIL_MACRO; uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, macronode, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_db_destroy(&test_db); cil_destroy_macro(macro); } void test_cil_build_ast_node_helper_gen_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_call_neg(CuTest *tc) { char *line[] = {"(", "call", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_optional_neg(CuTest *tc) { char *line[] = {"(", "optional", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "open_perms", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_policycap_neg(CuTest *tc) { char *line[] = {"(", "policycap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_args_build *extra_args = NULL; uint32_t finished = 0; int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_last_child_helper(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_last_child_helper(test_tree->root->cl_head->cl_head, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_last_child_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = __cil_build_ast_last_child_helper(test_tree->root->cl_head->cl_head, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol/cil/test/unit/test_cil_build_ast.h0100644 0000000 0000000 00000156235 13756670065 020163 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_BUILD_AST_H_ #define TEST_CIL_BUILD_AST_H_ #include "CuTest.h" void test_cil_parse_to_list(CuTest *); void test_cil_parse_to_list_currnull_neg(CuTest *); void test_cil_parse_to_list_listnull_neg(CuTest *); void test_cil_set_to_list(CuTest *); void test_cil_set_to_list_tree_node_null_neg(CuTest *); void test_cil_set_to_list_cl_head_null_neg(CuTest *); void test_cil_set_to_list_listnull_neg(CuTest *); void test_cil_gen_block(CuTest *); void test_cil_gen_block_justblock_neg(CuTest *); void test_cil_gen_block_noname_neg(CuTest *); void test_cil_gen_block_dbnull_neg(CuTest *); void test_cil_gen_block_treenull_neg(CuTest *); void test_cil_gen_block_nodenull_neg(CuTest *); void test_cil_gen_block_nodeparentnull_neg(CuTest *); void test_cil_destroy_block(CuTest *); void test_cil_gen_blockinherit(CuTest *); void test_cil_gen_blockinherit_namelist_neg(CuTest *); void test_cil_gen_blockinherit_namenull_neg(CuTest *); void test_cil_gen_blockinherit_extra_neg(CuTest *); void test_cil_gen_blockinherit_dbnull_neg(CuTest *); void test_cil_gen_blockinherit_currnull_neg(CuTest *); void test_cil_gen_blockinherit_astnull_neg(CuTest *); void test_cil_gen_perm(CuTest *); void test_cil_gen_perm_noname_neg(CuTest *); void test_cil_gen_perm_dbnull_neg(CuTest *); void test_cil_gen_perm_currnull_neg(CuTest *); void test_cil_gen_perm_astnull_neg(CuTest *); void test_cil_gen_perm_nodenull_neg(CuTest *); void test_cil_gen_permset(CuTest *); void test_cil_gen_permset_noname_neg(CuTest *); void test_cil_gen_permset_nameinparens_neg(CuTest *); void test_cil_gen_permset_noperms_neg(CuTest *); void test_cil_gen_permset_emptyperms_neg(CuTest *); void test_cil_gen_permset_extra_neg(CuTest *); void test_cil_gen_permset_dbnull_neg(CuTest *); void test_cil_gen_permset_currnull_neg(CuTest *); void test_cil_gen_permset_astnull_neg(CuTest *); void test_cil_gen_perm_nodes(CuTest *); void test_cil_gen_perm_nodes_failgen_neg(CuTest *); void test_cil_gen_perm_nodes_inval_perm_neg(CuTest *); void test_cil_fill_permset(CuTest *); void test_cil_fill_permset_sublist_neg(CuTest *); void test_cil_fill_permset_startpermnull_neg(CuTest *); void test_cil_fill_permset_permsetnull_neg(CuTest *); void test_cil_gen_in(CuTest *); void test_cil_gen_in_blockstrnull_neg(CuTest *); void test_cil_gen_in_extra_neg(CuTest *); void test_cil_gen_in_dbnull_neg(CuTest *); void test_cil_gen_in_currnull_neg(CuTest *); void test_cil_gen_in_astnull_neg(CuTest *); void test_cil_gen_class(CuTest *); void test_cil_gen_class_noname_neg(CuTest *); void test_cil_gen_class_nodenull_neg(CuTest *); void test_cil_gen_class_dbnull_neg(CuTest *); void test_cil_gen_class_currnull_neg(CuTest *); void test_cil_gen_class_noclass_neg(CuTest *); void test_cil_gen_class_noclassname_neg(CuTest *); void test_cil_gen_class_namesublist_neg(CuTest *); void test_cil_gen_class_noperms(CuTest *); void test_cil_gen_class_permsnotinlist_neg(CuTest *); void test_cil_gen_class_extrapermlist_neg(CuTest *); void test_cil_gen_class_listinlist_neg(CuTest *); void test_cil_fill_classpermset_anonperms(CuTest *); void test_cil_fill_classpermset_anonperms_neg(CuTest *); void test_cil_fill_classpermset_namedperms(CuTest *); void test_cil_fill_classpermset_extra_neg(CuTest *); void test_cil_fill_classpermset_emptypermslist_neg(CuTest *); void test_cil_fill_classpermset_noperms_neg(CuTest *); void test_cil_fill_classpermset_noclass_neg(CuTest *); void test_cil_fill_classpermset_classnodenull_neg(CuTest *); void test_cil_fill_classpermset_cpsnull_neg(CuTest *); void test_cil_gen_classpermset(CuTest *); void test_cil_gen_classpermset_noname_neg(CuTest *); void test_cil_gen_classpermset_nameinparens_neg(CuTest *); void test_cil_gen_classpermset_noclass_neg(CuTest *); void test_cil_gen_classpermset_noperms_neg(CuTest *); void test_cil_gen_classpermset_emptyperms_neg(CuTest *); void test_cil_gen_classpermset_extra_neg(CuTest *); void test_cil_gen_classpermset_dbnull_neg(CuTest *); void test_cil_gen_classpermset_currnull_neg(CuTest *); void test_cil_gen_classpermset_astnull_neg(CuTest *); void test_cil_gen_classmap_perm(CuTest *); void test_cil_gen_classmap_perm_dupeperm_neg(CuTest *); void test_cil_gen_classmap_perm_dbnull_neg(CuTest *tc); void test_cil_gen_classmap_perm_currnull_neg(CuTest *tc); void test_cil_gen_classmap_perm_astnull_neg(CuTest *tc); void test_cil_gen_classmap(CuTest *); void test_cil_gen_classmap_extra_neg(CuTest *); void test_cil_gen_classmap_noname_neg(CuTest *); void test_cil_gen_classmap_emptyperms_neg(CuTest *); void test_cil_gen_classmap_dbnull_neg(CuTest *tc); void test_cil_gen_classmap_currnull_neg(CuTest *tc); void test_cil_gen_classmap_astnull_neg(CuTest *tc); void test_cil_gen_classmapping_anonpermset(CuTest *); void test_cil_gen_classmapping_anonpermset_neg(CuTest *); void test_cil_gen_classmapping_namedpermset(CuTest *); void test_cil_gen_classmapping_noclassmapname_neg(CuTest *); void test_cil_gen_classmapping_noclassmapperm_neg(CuTest *); void test_cil_gen_classmapping_nopermissionsets_neg(CuTest *); void test_cil_gen_classmapping_emptyperms_neg(CuTest *); void test_cil_gen_classmapping_dbnull_neg(CuTest *tc); void test_cil_gen_classmapping_currnull_neg(CuTest *tc); void test_cil_gen_classmapping_astnull_neg(CuTest *tc); void test_cil_gen_common(CuTest *); void test_cil_gen_common_dbnull_neg(CuTest *tc); void test_cil_gen_common_currnull_neg(CuTest *tc); void test_cil_gen_common_astnull_neg(CuTest *tc); void test_cil_gen_common_noname_neg(CuTest *tc); void test_cil_gen_common_twoperms_neg(CuTest *tc); void test_cil_gen_common_permsublist_neg(CuTest *tc); void test_cil_gen_common_noperms_neg(CuTest *tc); void test_cil_gen_sid(CuTest *); void test_cil_gen_sid_noname_neg(CuTest *); void test_cil_gen_sid_nameinparens_neg(CuTest *); void test_cil_gen_sid_extra_neg(CuTest *); void test_cil_gen_sid_dbnull_neg(CuTest *); void test_cil_gen_sid_currnull_neg(CuTest *); void test_cil_gen_sid_astnull_neg(CuTest *); void test_cil_gen_sidcontext(CuTest *); void test_cil_gen_sidcontext_namedcontext(CuTest *); void test_cil_gen_sidcontext_halfcontext_neg(CuTest *); void test_cil_gen_sidcontext_noname_neg(CuTest *); void test_cil_gen_sidcontext_empty_neg(CuTest *); void test_cil_gen_sidcontext_nocontext_neg(CuTest *); void test_cil_gen_sidcontext_dblname_neg(CuTest *); void test_cil_gen_sidcontext_dbnull_neg(CuTest *); void test_cil_gen_sidcontext_pcurrnull_neg(CuTest *); void test_cil_gen_sidcontext_astnodenull_neg(CuTest *); void test_cil_gen_type(CuTest *); void test_cil_gen_type_neg(CuTest *); void test_cil_gen_type_dbnull_neg(CuTest *tc); void test_cil_gen_type_currnull_neg(CuTest *tc); void test_cil_gen_type_astnull_neg(CuTest *tc); void test_cil_gen_type_extra_neg(CuTest *tc); void test_cil_gen_typeattribute(CuTest *); void test_cil_gen_typeattribute_dbnull_neg(CuTest *tc); void test_cil_gen_typeattribute_currnull_neg(CuTest *tc); void test_cil_gen_typeattribute_astnull_neg(CuTest *tc); void test_cil_gen_typeattribute_extra_neg(CuTest *tc); void test_cil_gen_typeattr(CuTest *); void test_cil_gen_typeattr_dbnull_neg(CuTest *); void test_cil_gen_typeattr_currnull_neg(CuTest *); void test_cil_gen_typeattr_astnull_neg(CuTest *); void test_cil_gen_typeattr_typenull_neg(CuTest *); void test_cil_gen_typeattr_attrnull_neg(CuTest *); void test_cil_gen_typeattr_attrlist_neg(CuTest *); void test_cil_gen_typeattr_extra_neg(CuTest *); void test_cil_gen_typebounds(CuTest *); void test_cil_gen_typebounds_notype1_neg(CuTest *); void test_cil_gen_typebounds_type1inparens_neg(CuTest *); void test_cil_gen_typebounds_notype2_neg(CuTest *); void test_cil_gen_typebounds_type2inparens_neg(CuTest *); void test_cil_gen_typebounds_extra_neg(CuTest *); void test_cil_gen_typebounds_dbnull_neg(CuTest *); void test_cil_gen_typebounds_currnull_neg(CuTest *); void test_cil_gen_typebounds_astnull_neg(CuTest *); void test_cil_gen_typepermissive(CuTest *); void test_cil_gen_typepermissive_noname_neg(CuTest *); void test_cil_gen_typepermissive_typeinparens_neg(CuTest *); void test_cil_gen_typepermissive_extra_neg(CuTest *); void test_cil_gen_typepermissive_dbnull_neg(CuTest *); void test_cil_gen_typepermissive_currnull_neg(CuTest *); void test_cil_gen_typepermissive_astnull_neg(CuTest *); void test_cil_gen_nametypetransition(CuTest *); void test_cil_gen_nametypetransition_nostr_neg(CuTest *); void test_cil_gen_nametypetransition_strinparens_neg(CuTest *); void test_cil_gen_nametypetransition_nosrc_neg(CuTest *); void test_cil_gen_nametypetransition_srcinparens_neg(CuTest *); void test_cil_gen_nametypetransition_notgt_neg(CuTest *); void test_cil_gen_nametypetransition_tgtinparens_neg(CuTest *); void test_cil_gen_nametypetransition_noclass_neg(CuTest *); void test_cil_gen_nametypetransition_classinparens_neg(CuTest *); void test_cil_gen_nametypetransition_nodest_neg(CuTest *); void test_cil_gen_nametypetransition_destinparens_neg(CuTest *); void test_cil_gen_nametypetransition_extra_neg(CuTest *); void test_cil_gen_nametypetransition_dbnull_neg(CuTest *); void test_cil_gen_nametypetransition_currnull_neg(CuTest *); void test_cil_gen_nametypetransition_astnull_neg(CuTest *); void test_cil_gen_rangetransition(CuTest *); void test_cil_gen_rangetransition_namedtransition(CuTest *); void test_cil_gen_rangetransition_anon_low_l(CuTest *); void test_cil_gen_rangetransition_anon_low_l_neg(CuTest *); void test_cil_gen_rangetransition_anon_high_l(CuTest *); void test_cil_gen_rangetransition_anon_high_l_neg(CuTest *); void test_cil_gen_rangetransition_dbnull_neg(CuTest *); void test_cil_gen_rangetransition_currnull_neg(CuTest *); void test_cil_gen_rangetransition_astnull_neg(CuTest *); void test_cil_gen_rangetransition_nofirsttype_neg(CuTest *); void test_cil_gen_rangetransition_firsttype_inparens_neg(CuTest *); void test_cil_gen_rangetransition_nosecondtype_neg(CuTest *); void test_cil_gen_rangetransition_secondtype_inparens_neg(CuTest *); void test_cil_gen_rangetransition_noclass_neg(CuTest *); void test_cil_gen_rangetransition_class_inparens_neg(CuTest *); void test_cil_gen_rangetransition_nolevel_l_neg(CuTest *); void test_cil_gen_rangetransition_nolevel_h_neg(CuTest *); void test_cil_gen_rangetransition_extra_neg(CuTest *); void test_cil_gen_expr_stack_and(CuTest *); void test_cil_gen_expr_stack_or(CuTest *); void test_cil_gen_expr_stack_xor(CuTest *); void test_cil_gen_expr_stack_not(CuTest *); void test_cil_gen_expr_stack_not_noexpr_neg(CuTest *); void test_cil_gen_expr_stack_not_extraexpr_neg(CuTest *); void test_cil_gen_expr_stack_eq(CuTest *); void test_cil_gen_expr_stack_neq(CuTest *); void test_cil_gen_expr_stack_nested(CuTest *); void test_cil_gen_expr_stack_nested_neg(CuTest *); void test_cil_gen_expr_stack_nested_emptyargs_neg(CuTest *); void test_cil_gen_expr_stack_nested_missingoperator_neg(CuTest *); void test_cil_gen_expr_stack_arg1null_neg(CuTest *); void test_cil_gen_expr_stack_arg2null_neg(CuTest *); void test_cil_gen_expr_stack_extraarg_neg(CuTest *); void test_cil_gen_expr_stack_currnull_neg(CuTest *); void test_cil_gen_expr_stack_stacknull_neg(CuTest *); void test_cil_gen_boolif_multiplebools_true(CuTest *); void test_cil_gen_boolif_multiplebools_false(CuTest *); void test_cil_gen_boolif_multiplebools_unknowncond_neg(CuTest *); void test_cil_gen_boolif_true(CuTest *); void test_cil_gen_boolif_false(CuTest *); void test_cil_gen_boolif_unknowncond_neg(CuTest *); void test_cil_gen_boolif_nested(CuTest *); void test_cil_gen_boolif_nested_neg(CuTest *); void test_cil_gen_boolif_extra_neg(CuTest *); void test_cil_gen_boolif_extra_parens_neg(CuTest *); void test_cil_gen_boolif_nocond(CuTest *); void test_cil_gen_boolif_neg(CuTest *); void test_cil_gen_boolif_dbnull_neg(CuTest *); void test_cil_gen_boolif_currnull_neg(CuTest *); void test_cil_gen_boolif_astnull_neg(CuTest *); void test_cil_gen_boolif_nocond_neg(CuTest *); void test_cil_gen_boolif_notruelist_neg(CuTest *); void test_cil_gen_boolif_empty_cond_neg(CuTest *); void test_cil_gen_else(CuTest *); void test_cil_gen_else_neg(CuTest *); void test_cil_gen_else_dbnull_neg(CuTest *); void test_cil_gen_else_currnull_neg(CuTest *); void test_cil_gen_else_astnull_neg(CuTest *); void test_cil_gen_tunif_multiplebools_true(CuTest *); void test_cil_gen_tunif_multiplebools_false(CuTest *); void test_cil_gen_tunif_multiplebools_unknowncond_neg(CuTest *); void test_cil_gen_tunif_true(CuTest *); void test_cil_gen_tunif_false(CuTest *); void test_cil_gen_tunif_unknowncond_neg(CuTest *); void test_cil_gen_tunif_nocond(CuTest *); void test_cil_gen_tunif_nested(CuTest *); void test_cil_gen_tunif_nested_neg(CuTest *); void test_cil_gen_tunif_extra_neg(CuTest *); void test_cil_gen_tunif_extra_parens_neg(CuTest *); void test_cil_gen_tunif_neg(CuTest *); void test_cil_gen_tunif_dbnull_neg(CuTest *); void test_cil_gen_tunif_currnull_neg(CuTest *); void test_cil_gen_tunif_astnull_neg(CuTest *); void test_cil_gen_tunif_nocond_neg(CuTest *); void test_cil_gen_tunif_notruelist_neg(CuTest *); void test_cil_gen_condblock_true(CuTest *); void test_cil_gen_condblock_false(CuTest *); void test_cil_gen_condblock_dbnull_neg(CuTest *); void test_cil_gen_condblock_currnull_neg(CuTest *); void test_cil_gen_condblock_astnull_neg(CuTest *); void test_cil_gen_condblock_nocond_neg(CuTest *); void test_cil_gen_condblock_extra_neg(CuTest *); void test_cil_gen_typealias(CuTest *); void test_cil_gen_typealias_incomplete_neg(CuTest *); void test_cil_gen_typealias_incomplete_neg2(CuTest *); void test_cil_gen_typealias_extratype_neg(CuTest *); void test_cil_gen_typealias_dbnull_neg(CuTest *tc); void test_cil_gen_typealias_currnull_neg(CuTest *tc); void test_cil_gen_typealias_astnull_neg(CuTest *tc); void test_cil_gen_typeattributeset(CuTest *); void test_cil_gen_typeattributeset_and_two_types(CuTest *); void test_cil_gen_typeattributeset_not(CuTest *); void test_cil_gen_typeattributeset_exclude_attr(CuTest *); void test_cil_gen_typeattributeset_exclude_neg(CuTest *); void test_cil_gen_typeattributeset_dbnull_neg(CuTest *); void test_cil_gen_typeattributeset_currnull_neg(CuTest *); void test_cil_gen_typeattributeset_astnull_neg(CuTest *); void test_cil_gen_typeattributeset_noname_neg(CuTest *); void test_cil_gen_typeattributeset_nameinparens_neg(CuTest *); void test_cil_gen_typeattributeset_emptylists_neg(CuTest *); void test_cil_gen_typeattributeset_listinparens_neg(CuTest *); void test_cil_gen_typeattributeset_extra_neg(CuTest *); void test_cil_gen_userbounds(CuTest *); void test_cil_gen_userbounds_notype1_neg(CuTest *); void test_cil_gen_userbounds_type1_inparens_neg(CuTest *); void test_cil_gen_userbounds_notype2_neg(CuTest *); void test_cil_gen_userbounds_type2_inparens_neg(CuTest *); void test_cil_gen_userbounds_extra_neg(CuTest *); void test_cil_gen_userbounds_dbnull_neg(CuTest *); void test_cil_gen_userbounds_currnull_neg(CuTest *); void test_cil_gen_userbounds_astnull_neg(CuTest *); void test_cil_gen_role(CuTest *); void test_cil_gen_role_dbnull_neg(CuTest *tc); void test_cil_gen_role_currnull_neg(CuTest *tc); void test_cil_gen_role_astnull_neg(CuTest *tc); void test_cil_gen_role_extrarole_neg(CuTest *tc); void test_cil_gen_role_noname_neg(CuTest *tc); void test_cil_gen_roletransition(CuTest *); void test_cil_gen_roletransition_currnull_neg(CuTest *); void test_cil_gen_roletransition_astnull_neg(CuTest *); void test_cil_gen_roletransition_srcnull_neg(CuTest *); void test_cil_gen_roletransition_tgtnull_neg(CuTest *); void test_cil_gen_roletransition_resultnull_neg(CuTest *); void test_cil_gen_roletransition_extra_neg(CuTest *); void test_cil_gen_bool_true(CuTest *); void test_cil_gen_bool_tunable_true(CuTest *); void test_cil_gen_bool_false(CuTest *); void test_cil_gen_bool_tunable_false(CuTest *); void test_cil_gen_bool_none_neg(CuTest *); void test_cil_gen_bool_dbnull_neg(CuTest *); void test_cil_gen_bool_currnull_neg(CuTest *); void test_cil_gen_bool_astnull_neg(CuTest *); void test_cil_gen_bool_notbool_neg(CuTest *); void test_cil_gen_bool_boolname_neg(CuTest *); void test_cil_gen_bool_extraname_false_neg(CuTest *); void test_cil_gen_bool_extraname_true_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1type(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1t1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t2type(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t2t2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1role(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1r1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r2role(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r2r2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1t2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_r1r2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1r2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1u2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1user(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1u1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u2user(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u2u2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l2h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1h1(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1l2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not(CuTest *); void test_cil_gen_constrain_expr_stack_not_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not_emptyparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not_extraparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or(CuTest *); void test_cil_gen_constrain_expr_stack_or_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and(CuTest *); void test_cil_gen_constrain_expr_stack_and_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom(CuTest *); void test_cil_gen_constrain_expr_stack_dom_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby(CuTest *); void test_cil_gen_constrain_expr_stack_domby_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_currnull_neg(CuTest *); void test_cil_gen_constrain_expr_stack_stacknull_neg(CuTest *); void test_cil_gen_constrain_expr_stack_operatorinparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incorrectcall_neg(CuTest *); void test_cil_gen_roleallow(CuTest *); void test_cil_gen_roleallow_dbnull_neg(CuTest *); void test_cil_gen_roleallow_currnull_neg(CuTest *); void test_cil_gen_roleallow_astnull_neg(CuTest *); void test_cil_gen_roleallow_srcnull_neg(CuTest *); void test_cil_gen_roleallow_tgtnull_neg(CuTest *); void test_cil_gen_roleallow_extra_neg(CuTest *); void test_cil_gen_rolebounds(CuTest *); void test_cil_gen_rolebounds_norole1_neg(CuTest *); void test_cil_gen_rolebounds_role1_inparens_neg(CuTest *); void test_cil_gen_rolebounds_norole2_neg(CuTest *); void test_cil_gen_rolebounds_role2_inparens_neg(CuTest *); void test_cil_gen_rolebounds_extra_neg(CuTest *); void test_cil_gen_rolebounds_dbnull_neg(CuTest *); void test_cil_gen_rolebounds_currnull_neg(CuTest *); void test_cil_gen_rolebounds_astnull_neg(CuTest *); void test_cil_gen_avrule(CuTest *); void test_cil_gen_avrule_permset(CuTest *); void test_cil_gen_avrule_permset_anon(CuTest *); void test_cil_gen_avrule_extra_neg(CuTest *); void test_cil_gen_avrule_sourceparens(CuTest *); void test_cil_gen_avrule_sourceemptyparen_neg(CuTest *); void test_cil_gen_avrule_targetparens(CuTest *); void test_cil_gen_avrule_targetemptyparen_neg(CuTest *); void test_cil_gen_avrule_currnull_neg(CuTest *tc); void test_cil_gen_avrule_astnull_neg(CuTest *tc); void test_cil_gen_avrule_sourcedomainnull_neg(CuTest *tc); void test_cil_gen_avrule_targetdomainnull_neg(CuTest *tc); void test_cil_gen_avrule_objectclassnull_neg(CuTest *tc); void test_cil_gen_avrule_permsnull_neg(CuTest *tc); void test_cil_gen_avrule_twolists_neg(CuTest *); //TODO: add cases to cover parse_current->next->cl_head != NULL || parse_current->next->next->cl_head != NULL // || parse_current->next->next->next->cl_head != NULL void test_cil_gen_type_rule_transition(CuTest *); void test_cil_gen_type_rule_transition_currnull_neg(CuTest *); void test_cil_gen_type_rule_transition_astnull_neg(CuTest *); void test_cil_gen_type_rule_transition_srcnull_neg(CuTest *); void test_cil_gen_type_rule_transition_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_transition_objnull_neg(CuTest *); void test_cil_gen_type_rule_transition_resultnull_neg(CuTest *); void test_cil_gen_type_rule_transition_extra_neg(CuTest *); void test_cil_gen_type_rule_change(CuTest *); void test_cil_gen_type_rule_change_currnull_neg(CuTest *); void test_cil_gen_type_rule_change_astnull_neg(CuTest *); void test_cil_gen_type_rule_change_srcnull_neg(CuTest *); void test_cil_gen_type_rule_change_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_change_objnull_neg(CuTest *); void test_cil_gen_type_rule_change_resultnull_neg(CuTest *); void test_cil_gen_type_rule_change_extra_neg(CuTest *); void test_cil_gen_type_rule_member(CuTest *); void test_cil_gen_type_rule_member_currnull_neg(CuTest *); void test_cil_gen_type_rule_member_astnull_neg(CuTest *); void test_cil_gen_type_rule_member_srcnull_neg(CuTest *); void test_cil_gen_type_rule_member_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_member_objnull_neg(CuTest *); void test_cil_gen_type_rule_member_resultnull_neg(CuTest *); void test_cil_gen_type_rule_member_extra_neg(CuTest *); void test_cil_gen_user(CuTest *); void test_cil_gen_user_dbnull_neg(CuTest *); void test_cil_gen_user_currnull_neg(CuTest *); void test_cil_gen_user_astnull_neg(CuTest *); void test_cil_gen_user_nouser_neg(CuTest *); void test_cil_gen_user_xsinfo_neg(CuTest *); void test_cil_gen_userlevel(CuTest *); void test_cil_gen_userlevel_anon_level(CuTest *); void test_cil_gen_userlevel_anon_level_neg(CuTest *); void test_cil_gen_userlevel_usernull_neg(CuTest *); void test_cil_gen_userlevel_userrange_neg(CuTest *); void test_cil_gen_userlevel_levelnull_neg(CuTest *); void test_cil_gen_userlevel_levelrangeempty_neg(CuTest *); void test_cil_gen_userlevel_extra_neg(CuTest *); void test_cil_gen_userlevel_dbnull_neg(CuTest *); void test_cil_gen_userlevel_currnull_neg(CuTest *); void test_cil_gen_userlevel_astnull_neg(CuTest *); void test_cil_gen_userrange_named(CuTest *); void test_cil_gen_userrange_anon(CuTest *); void test_cil_gen_userrange_usernull_neg(CuTest *); void test_cil_gen_userrange_anonuser_neg(CuTest *); void test_cil_gen_userrange_rangenamenull_neg(CuTest *); void test_cil_gen_userrange_anonrangeinvalid_neg(CuTest *); void test_cil_gen_userrange_anonrangeempty_neg(CuTest *); void test_cil_gen_userrange_extra_neg(CuTest *); void test_cil_gen_userrange_dbnull_neg(CuTest *); void test_cil_gen_userrange_currnull_neg(CuTest *); void test_cil_gen_userrange_astnull_neg(CuTest *); void test_cil_gen_sensitivity(CuTest *); void test_cil_gen_sensitivity_dbnull_neg(CuTest *); void test_cil_gen_sensitivity_currnull_neg(CuTest *); void test_cil_gen_sensitivity_astnull_neg(CuTest *); void test_cil_gen_sensitivity_sensnull_neg(CuTest *); void test_cil_gen_sensitivity_senslist_neg(CuTest *); void test_cil_gen_sensitivity_extra_neg(CuTest *); void test_cil_gen_sensalias(CuTest *); void test_cil_gen_sensalias_dbnull_neg(CuTest *); void test_cil_gen_sensalias_currnull_neg(CuTest *); void test_cil_gen_sensalias_astnull_neg(CuTest *); void test_cil_gen_sensalias_sensnull_neg(CuTest *); void test_cil_gen_sensalias_senslist_neg(CuTest *); void test_cil_gen_sensalias_aliasnull_neg(CuTest *); void test_cil_gen_sensalias_aliaslist_neg(CuTest *); void test_cil_gen_sensalias_extra_neg(CuTest *); void test_cil_gen_category(CuTest *); void test_cil_gen_category_dbnull_neg(CuTest *); void test_cil_gen_category_astnull_neg(CuTest *); void test_cil_gen_category_currnull_neg(CuTest *); void test_cil_gen_category_catnull_neg(CuTest *); void test_cil_gen_category_catlist_neg(CuTest *); void test_cil_gen_category_extra_neg(CuTest *); void test_cil_gen_catset(CuTest *); void test_cil_gen_catset_dbnull_neg(CuTest *); void test_cil_gen_catset_currnull_neg(CuTest *); void test_cil_gen_catset_astnull_neg(CuTest *); void test_cil_gen_catset_namenull_neg(CuTest *); void test_cil_gen_catset_setnull_neg(CuTest *); void test_cil_gen_catset_namelist_neg(CuTest *); void test_cil_gen_catset_extra_neg(CuTest *); void test_cil_gen_catset_nodefail_neg(CuTest *); void test_cil_gen_catset_notset_neg(CuTest *); void test_cil_gen_catset_settolistfail_neg(CuTest *); void test_cil_gen_catalias(CuTest *); void test_cil_gen_catalias_dbnull_neg(CuTest *); void test_cil_gen_catalias_currnull_neg(CuTest *); void test_cil_gen_catalias_astnull_neg(CuTest *); void test_cil_gen_catalias_catnull_neg(CuTest *); void test_cil_gen_catalias_aliasnull_neg(CuTest *); void test_cil_gen_catalias_extra_neg(CuTest *); void test_cil_gen_catrange(CuTest *); void test_cil_gen_catrange_noname_neg(CuTest *); void test_cil_gen_catrange_norange_neg(CuTest *); void test_cil_gen_catrange_emptyrange_neg(CuTest *); void test_cil_gen_catrange_extrarange_neg(CuTest *); void test_cil_gen_catrange_dbnull_neg(CuTest *); void test_cil_gen_catrange_currnull_neg(CuTest *); void test_cil_gen_catrange_astnull_neg(CuTest *); void test_cil_gen_catrange_extra_neg(CuTest *); void test_cil_gen_roletype(CuTest *tc); void test_cil_gen_roletype_currnull_neg(CuTest *tc); void test_cil_gen_roletype_dbnull_neg(CuTest *tc); void test_cil_gen_roletype_astnull_neg(CuTest *tc); void test_cil_gen_roletype_empty_neg(CuTest *tc); void test_cil_gen_roletype_rolelist_neg(CuTest *tc); void test_cil_gen_roletype_roletype_sublist_neg(CuTest *tc); void test_cil_gen_roletype_typelist_neg(CuTest *tc); void test_cil_gen_userrole(CuTest *tc); void test_cil_gen_userrole_currnull_neg(CuTest *tc); void test_cil_gen_userrole_dbnull_neg(CuTest *tc); void test_cil_gen_userrole_astnull_neg(CuTest *tc); void test_cil_gen_userrole_empty_neg(CuTest *tc); void test_cil_gen_userrole_userlist_neg(CuTest *tc); void test_cil_gen_userrole_userrole_sublist_neg(CuTest *tc); void test_cil_gen_userrole_rolelist_neg(CuTest *tc); void test_cil_gen_classcommon(CuTest *tc); void test_cil_gen_classcommon_dbnull_neg(CuTest *tc); void test_cil_gen_classcommon_currnull_neg(CuTest *tc); void test_cil_gen_classcommon_astnull_neg(CuTest *tc); void test_cil_gen_classcommon_missingclassname_neg(CuTest *tc); void test_cil_gen_classcommon_noperms_neg(CuTest *tc); void test_cil_gen_classcommon_extraperms_neg(CuTest *tc); void test_cil_gen_catorder(CuTest *tc); void test_cil_gen_catorder_dbnull_neg(CuTest *tc); void test_cil_gen_catorder_currnull_neg(CuTest *tc); void test_cil_gen_catorder_astnull_neg(CuTest *tc); void test_cil_gen_catorder_missingcats_neg(CuTest *tc); void test_cil_gen_catorder_nosublist_neg(CuTest *tc); void test_cil_gen_catorder_nestedcat_neg(CuTest *tc); void test_cil_gen_dominance(CuTest *tc); void test_cil_gen_dominance_dbnull_neg(CuTest *tc); void test_cil_gen_dominance_currnull_neg(CuTest *tc); void test_cil_gen_dominance_astnull_neg(CuTest *tc); void test_cil_gen_dominance_nosensitivities_neg(CuTest *tc); void test_cil_gen_dominance_nosublist_neg(CuTest *tc); void test_cil_gen_senscat(CuTest *tc); void test_cil_gen_senscat_nosublist(CuTest *); void test_cil_gen_senscat_dbnull_neg(CuTest *tc); void test_cil_gen_senscat_currnull_neg(CuTest *tc); void test_cil_gen_senscat_astnull_neg(CuTest *tc); void test_cil_gen_senscat_nosensitivities_neg(CuTest *tc); void test_cil_gen_senscat_sublist_neg(CuTest *); void test_cil_gen_senscat_nocat_neg(CuTest *); void test_cil_fill_level(CuTest *tc); void test_cil_fill_level_sensnull_neg(CuTest *tc); void test_cil_fill_level_levelnull_neg(CuTest *tc); void test_cil_fill_level_nocat(CuTest *tc); void test_cil_fill_level_emptycat_neg(CuTest *tc); void test_cil_gen_level(CuTest *tc); void test_cil_gen_level_nameinparens_neg(CuTest *tc); void test_cil_gen_level_emptysensparens_neg(CuTest *tc); void test_cil_gen_level_extra_neg(CuTest *tc); void test_cil_gen_level_emptycat_neg(CuTest *tc); void test_cil_gen_level_noname_neg(CuTest *tc); void test_cil_gen_level_nosens_neg(CuTest *tc); void test_cil_gen_level_dbnull_neg(CuTest *tc); void test_cil_gen_level_currnull_neg(CuTest *tc); void test_cil_gen_level_astnull_neg(CuTest *tc); void test_cil_gen_levelrange(CuTest *tc); void test_cil_gen_levelrange_rangeinvalid_neg(CuTest *tc); void test_cil_gen_levelrange_namenull_neg(CuTest *tc); void test_cil_gen_levelrange_rangenull_neg(CuTest *tc); void test_cil_gen_levelrange_rangeempty_neg(CuTest *tc); void test_cil_gen_levelrange_extra_neg(CuTest *tc); void test_cil_gen_levelrange_dbnull_neg(CuTest *tc); void test_cil_gen_levelrange_currnull_neg(CuTest *tc); void test_cil_gen_levelrange_astnull_neg(CuTest *tc); void test_cil_gen_constrain(CuTest *tc); void test_cil_gen_constrain_neg(CuTest *tc); void test_cil_gen_constrain_classset_neg(CuTest *tc); void test_cil_gen_constrain_classset_noclass_neg(CuTest *tc); void test_cil_gen_constrain_classset_noperm_neg(CuTest *tc); void test_cil_gen_constrain_permset_neg(CuTest *tc); void test_cil_gen_constrain_permset_noclass_neg(CuTest *tc); void test_cil_gen_constrain_permset_noperm_neg(CuTest *tc); void test_cil_gen_constrain_expression_neg(CuTest *tc); void test_cil_gen_constrain_dbnull_neg(CuTest *tc); void test_cil_gen_constrain_currnull_neg(CuTest *tc); void test_cil_gen_constrain_astnull_neg(CuTest *tc); void test_cil_fill_context(CuTest *tc); void test_cil_fill_context_unnamedlvl(CuTest *tc); void test_cil_fill_context_nocontext_neg(CuTest *tc); void test_cil_fill_context_nouser_neg(CuTest *tc); void test_cil_fill_context_norole_neg(CuTest *tc); void test_cil_fill_context_notype_neg(CuTest *tc); void test_cil_fill_context_nolowlvl_neg(CuTest *tc); void test_cil_fill_context_nohighlvl_neg(CuTest *tc); void test_cil_fill_context_unnamedlvl_nocontextlow_neg(CuTest *tc); void test_cil_fill_context_unnamedlvl_nocontexthigh_neg(CuTest *tc); void test_cil_gen_context(CuTest *tc); void test_cil_gen_context_notinparens_neg(CuTest *tc); void test_cil_gen_context_extralevel_neg(CuTest *tc); void test_cil_gen_context_emptycontext_neg(CuTest *tc); void test_cil_gen_context_extra_neg(CuTest *tc); void test_cil_gen_context_doubleparen_neg(CuTest *tc); void test_cil_gen_context_norole_neg(CuTest *tc); void test_cil_gen_context_roleinparens_neg(CuTest *tc); void test_cil_gen_context_notype_neg(CuTest *tc); void test_cil_gen_context_typeinparens_neg(CuTest *tc); void test_cil_gen_context_nolevels_neg(CuTest *tc); void test_cil_gen_context_nosecondlevel_neg(CuTest *tc); void test_cil_gen_context_noname_neg(CuTest *tc); void test_cil_gen_context_nouser_neg(CuTest *tc); void test_cil_gen_context_dbnull_neg(CuTest *tc); void test_cil_gen_context_currnull_neg(CuTest *tc); void test_cil_gen_context_astnull_neg(CuTest *tc); void test_cil_gen_filecon_file(CuTest *tc); void test_cil_gen_filecon_dir(CuTest *tc); void test_cil_gen_filecon_char(CuTest *tc); void test_cil_gen_filecon_block(CuTest *tc); void test_cil_gen_filecon_socket(CuTest *tc); void test_cil_gen_filecon_pipe(CuTest *tc); void test_cil_gen_filecon_symlink(CuTest *tc); void test_cil_gen_filecon_any(CuTest *tc); void test_cil_gen_filecon_neg(CuTest *tc); void test_cil_gen_filecon_anon_context(CuTest *tc); void test_cil_gen_filecon_dbnull_neg(CuTest *tc); void test_cil_gen_filecon_currnull_neg(CuTest *tc); void test_cil_gen_filecon_astnull_neg(CuTest *tc); void test_cil_gen_filecon_str1null_neg(CuTest *tc); void test_cil_gen_filecon_str1_inparens_neg(CuTest *tc); void test_cil_gen_filecon_str2null_neg(CuTest *tc); void test_cil_gen_filecon_str2_inparens_neg(CuTest *tc); void test_cil_gen_filecon_classnull_neg(CuTest *tc); void test_cil_gen_filecon_class_inparens_neg(CuTest *tc); void test_cil_gen_filecon_contextnull_neg(CuTest *tc); void test_cil_gen_filecon_context_neg(CuTest *tc); void test_cil_gen_filecon_extra_neg(CuTest *tc); void test_cil_gen_portcon_udp(CuTest *tc); void test_cil_gen_portcon_tcp(CuTest *tc); void test_cil_gen_portcon_unknownprotocol_neg(CuTest *tc); void test_cil_gen_portcon_anon_context(CuTest *tc); void test_cil_gen_portcon_portrange(CuTest *tc); void test_cil_gen_portcon_portrange_one_neg(CuTest *tc); void test_cil_gen_portcon_portrange_morethanone_neg(CuTest *tc); void test_cil_gen_portcon_singleport_neg(CuTest *tc); void test_cil_gen_portcon_lowport_neg(CuTest *tc); void test_cil_gen_portcon_highport_neg(CuTest *tc); void test_cil_gen_portcon_dbnull_neg(CuTest *tc); void test_cil_gen_portcon_currnull_neg(CuTest *tc); void test_cil_gen_portcon_astnull_neg(CuTest *tc); void test_cil_gen_portcon_str1null_neg(CuTest *tc); void test_cil_gen_portcon_str1parens_neg(CuTest *tc); void test_cil_gen_portcon_portnull_neg(CuTest *tc); void test_cil_gen_portcon_contextnull_neg(CuTest *tc); void test_cil_gen_portcon_context_neg(CuTest *tc); void test_cil_gen_portcon_extra_neg(CuTest *tc); void test_cil_fill_ipaddr(CuTest *tc); void test_cil_fill_ipaddr_addrnodenull_neg(CuTest *tc); void test_cil_fill_ipaddr_addrnull_neg(CuTest *tc); void test_cil_fill_ipaddr_addrinparens_neg(CuTest *tc); void test_cil_fill_ipaddr_extra_neg(CuTest *tc); void test_cil_gen_nodecon(CuTest *tc); void test_cil_gen_nodecon_anon_context(CuTest *tc); void test_cil_gen_nodecon_dbnull_neg(CuTest *tc); void test_cil_gen_nodecon_currnull_neg(CuTest *tc); void test_cil_gen_nodecon_astnull_neg(CuTest *tc); void test_cil_gen_nodecon_ipnull_neg(CuTest *tc); void test_cil_gen_nodecon_ipanon(CuTest *tc); void test_cil_gen_nodecon_ipanon_neg(CuTest *tc); void test_cil_gen_nodecon_netmasknull_neg(CuTest *tc); void test_cil_gen_nodecon_netmaskanon(CuTest *tc); void test_cil_gen_nodecon_netmaskanon_neg(CuTest *tc); void test_cil_gen_nodecon_contextnull_neg(CuTest *tc); void test_cil_gen_nodecon_context_neg(CuTest *tc); void test_cil_gen_nodecon_extra_neg(CuTest *tc); void test_cil_gen_genfscon(CuTest *tc); void test_cil_gen_genfscon_anon_context(CuTest *tc); void test_cil_gen_genfscon_dbnull_neg(CuTest *tc); void test_cil_gen_genfscon_currnull_neg(CuTest *tc); void test_cil_gen_genfscon_astnull_neg(CuTest *tc); void test_cil_gen_genfscon_typenull_neg(CuTest *tc); void test_cil_gen_genfscon_typeparens_neg(CuTest *tc); void test_cil_gen_genfscon_pathnull_neg(CuTest *tc); void test_cil_gen_genfscon_pathparens_neg(CuTest *tc); void test_cil_gen_genfscon_contextnull_neg(CuTest *tc); void test_cil_gen_genfscon_context_neg(CuTest *tc); void test_cil_gen_genfscon_extra_neg(CuTest *tc); void test_cil_gen_netifcon(CuTest *tc); void test_cil_gen_netifcon_nested(CuTest *tc); void test_cil_gen_netifcon_nested_neg(CuTest *tc); void test_cil_gen_netifcon_nested_emptysecondlist_neg(CuTest *tc); void test_cil_gen_netifcon_extra_nested_secondlist_neg(CuTest *tc); void test_cil_gen_netifcon_nested_missingobjects_neg(CuTest *tc); void test_cil_gen_netifcon_nested_secondnested_missingobjects_neg(CuTest *tc); void test_cil_gen_netifcon_dbnull_neg(CuTest *tc); void test_cil_gen_netifcon_currnull_neg(CuTest *tc); void test_cil_gen_netifcon_astnull_neg(CuTest *tc); void test_cil_gen_netifcon_ethmissing_neg(CuTest *tc); void test_cil_gen_netifcon_interfacemissing_neg(CuTest *tc); void test_cil_gen_netifcon_packetmissing_neg(CuTest *tc); void test_cil_gen_pirqcon(CuTest *tc); void test_cil_gen_pirqcon_pirqnotint_neg(CuTest *tc); void test_cil_gen_pirqcon_nopirq_neg(CuTest *tc); void test_cil_gen_pirqcon_pirqrange_neg(CuTest *tc); void test_cil_gen_pirqcon_nocontext_neg(CuTest *tc); void test_cil_gen_pirqcon_anoncontext_neg(CuTest *tc); void test_cil_gen_pirqcon_extra_neg(CuTest *tc); void test_cil_gen_pirqcon_dbnull_neg(CuTest *tc); void test_cil_gen_pirqcon_currnull_neg(CuTest *tc); void test_cil_gen_pirqcon_astnull_neg(CuTest *tc); void test_cil_gen_iomemcon(CuTest *tc); void test_cil_gen_iomemcon_iomemrange(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_firstnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_secondnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_empty_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_singleiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_noiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_nocontext_neg(CuTest *tc); void test_cil_gen_iomemcon_anoncontext_neg(CuTest *tc); void test_cil_gen_iomemcon_extra_neg(CuTest *tc); void test_cil_gen_iomemcon_dbnull_neg(CuTest *tc); void test_cil_gen_iomemcon_currnull_neg(CuTest *tc); void test_cil_gen_iomemcon_astnull_neg(CuTest *tc); void test_cil_gen_ioportcon(CuTest *tc); void test_cil_gen_ioportcon_ioportrange(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_firstnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_secondnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_empty_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_singleioport_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_noioport_neg(CuTest *tc); void test_cil_gen_ioportcon_nocontext_neg(CuTest *tc); void test_cil_gen_ioportcon_anoncontext_neg(CuTest *tc); void test_cil_gen_ioportcon_extra_neg(CuTest *tc); void test_cil_gen_ioportcon_dbnull_neg(CuTest *tc); void test_cil_gen_ioportcon_currnull_neg(CuTest *tc); void test_cil_gen_ioportcon_astnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon(CuTest *tc); void test_cil_gen_pcidevicecon_pcidevicenotint_neg(CuTest *tc); void test_cil_gen_pcidevicecon_nopcidevice_neg(CuTest *tc); void test_cil_gen_pcidevicecon_pcidevicerange_neg(CuTest *tc); void test_cil_gen_pcidevicecon_nocontext_neg(CuTest *tc); void test_cil_gen_pcidevicecon_anoncontext_neg(CuTest *tc); void test_cil_gen_pcidevicecon_extra_neg(CuTest *tc); void test_cil_gen_pcidevicecon_dbnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon_currnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon_astnull_neg(CuTest *tc); void test_cil_gen_fsuse_anoncontext(CuTest *tc); void test_cil_gen_fsuse_anoncontext_neg(CuTest *tc); void test_cil_gen_fsuse_xattr(CuTest *tc); void test_cil_gen_fsuse_task(CuTest *tc); void test_cil_gen_fsuse_transition(CuTest *tc); void test_cil_gen_fsuse_invalidtype_neg(CuTest *tc); void test_cil_gen_fsuse_notype_neg(CuTest *tc); void test_cil_gen_fsuse_typeinparens_neg(CuTest *tc); void test_cil_gen_fsuse_nofilesystem_neg(CuTest *tc); void test_cil_gen_fsuse_filesysteminparens_neg(CuTest *tc); void test_cil_gen_fsuse_nocontext_neg(CuTest *tc); void test_cil_gen_fsuse_emptyconparens_neg(CuTest *tc); void test_cil_gen_fsuse_extra_neg(CuTest *tc); void test_cil_gen_fsuse_dbnull_neg(CuTest *tc); void test_cil_gen_fsuse_currnull_neg(CuTest *tc); void test_cil_gen_fsuse_astnull_neg(CuTest *tc); void test_cil_gen_macro_noparams(CuTest *tc); void test_cil_gen_macro_type(CuTest *tc); void test_cil_gen_macro_role(CuTest *tc); void test_cil_gen_macro_user(CuTest *tc); void test_cil_gen_macro_sensitivity(CuTest *tc); void test_cil_gen_macro_category(CuTest *tc); void test_cil_gen_macro_catset(CuTest *tc); void test_cil_gen_macro_level(CuTest *tc); void test_cil_gen_macro_class(CuTest *tc); void test_cil_gen_macro_classmap(CuTest *tc); void test_cil_gen_macro_permset(CuTest *tc); void test_cil_gen_macro_duplicate(CuTest *tc); void test_cil_gen_macro_duplicate_neg(CuTest *tc); void test_cil_gen_macro_unknown_neg(CuTest *tc); void test_cil_gen_macro_dbnull_neg(CuTest *tc); void test_cil_gen_macro_currnull_neg(CuTest *tc); void test_cil_gen_macro_astnull_neg(CuTest *tc); void test_cil_gen_macro_unnamed_neg(CuTest *tc); void test_cil_gen_macro_noparam_name_neg(CuTest *tc); void test_cil_gen_macro_noparam_neg(CuTest *tc); void test_cil_gen_macro_nosecondparam_neg(CuTest *tc); void test_cil_gen_macro_emptyparam_neg(CuTest *tc); void test_cil_gen_macro_paramcontainsperiod_neg(CuTest *tc); void test_cil_gen_call(CuTest *tc); void test_cil_gen_call_noargs(CuTest *tc); void test_cil_gen_call_anon(CuTest *tc); void test_cil_gen_call_empty_call_neg(CuTest *tc); void test_cil_gen_call_dbnull_neg(CuTest *tc); void test_cil_gen_call_currnull_neg(CuTest *tc); void test_cil_gen_call_astnull_neg(CuTest *tc); void test_cil_gen_call_name_inparens_neg(CuTest *tc); void test_cil_gen_call_noname_neg(CuTest *tc); void test_cil_gen_optional(CuTest *tc); void test_cil_gen_optional_emptyoptional(CuTest *tc); void test_cil_gen_optional_dbnull_neg(CuTest *tc); void test_cil_gen_optional_currnull_neg(CuTest *tc); void test_cil_gen_optional_astnull_neg(CuTest *tc); void test_cil_gen_optional_unnamed_neg(CuTest *tc); void test_cil_gen_optional_extra_neg(CuTest *tc); void test_cil_gen_optional_nameinparens_neg(CuTest *tc); void test_cil_gen_optional_norule_neg(CuTest *tc); void test_cil_gen_policycap(CuTest *tc); void test_cil_gen_policycap_noname_neg(CuTest *tc); void test_cil_gen_policycap_nameinparens_neg(CuTest *tc); void test_cil_gen_policycap_extra_neg(CuTest *tc); void test_cil_gen_policycap_dbnull_neg(CuTest *tc); void test_cil_gen_policycap_currnull_neg(CuTest *tc); void test_cil_gen_policycap_astnull_neg(CuTest *tc); void test_cil_gen_ipaddr_ipv4(CuTest *tc); void test_cil_gen_ipaddr_ipv4_neg(CuTest *tc); void test_cil_gen_ipaddr_ipv6(CuTest *tc); void test_cil_gen_ipaddr_ipv6_neg(CuTest *tc); void test_cil_gen_ipaddr_noname_neg(CuTest *tc); void test_cil_gen_ipaddr_nameinparens_neg(CuTest *tc); void test_cil_gen_ipaddr_noip_neg(CuTest *tc); void test_cil_gen_ipaddr_ipinparens_neg(CuTest *tc); void test_cil_gen_ipaddr_extra_neg(CuTest *tc); void test_cil_gen_ipaddr_dbnull_neg(CuTest *tc); void test_cil_gen_ipaddr_currnull_neg(CuTest *tc); void test_cil_gen_ipaddr_astnull_neg(CuTest *tc); /* cil_build_ast test cases */ void test_cil_build_ast(CuTest *); void test_cil_build_ast_dbnull_neg(CuTest *); void test_cil_build_ast_astnull_neg(CuTest *); void test_cil_build_ast_suberr_neg(CuTest *); void test_cil_build_ast_treenull_neg(CuTest *); void test_cil_build_ast_node_helper_block(CuTest *); void test_cil_build_ast_node_helper_block_neg(CuTest *); void test_cil_build_ast_node_helper_blockinherit(CuTest *); void test_cil_build_ast_node_helper_blockinherit_neg(CuTest *); void test_cil_build_ast_node_helper_permset(CuTest *); void test_cil_build_ast_node_helper_permset_neg(CuTest *); void test_cil_build_ast_node_helper_in(CuTest *); void test_cil_build_ast_node_helper_in_neg(CuTest *); void test_cil_build_ast_node_helper_class(CuTest *); void test_cil_build_ast_node_helper_class_neg(CuTest *); void test_cil_build_ast_node_helper_classpermset(CuTest *); void test_cil_build_ast_node_helper_classpermset_neg(CuTest *); void test_cil_build_ast_node_helper_classmap(CuTest *); void test_cil_build_ast_node_helper_classmap_neg(CuTest *); void test_cil_build_ast_node_helper_classmapping(CuTest *); void test_cil_build_ast_node_helper_classmapping_neg(CuTest *); void test_cil_build_ast_node_helper_common(CuTest *); void test_cil_build_ast_node_helper_common_neg(CuTest *); void test_cil_build_ast_node_helper_sid(CuTest *); void test_cil_build_ast_node_helper_sid_neg(CuTest *); void test_cil_build_ast_node_helper_sidcontext(CuTest *); void test_cil_build_ast_node_helper_sidcontext_neg(CuTest *); void test_cil_build_ast_node_helper_user(CuTest *); void test_cil_build_ast_node_helper_user_neg(CuTest *); void test_cil_build_ast_node_helper_userlevel(CuTest *); void test_cil_build_ast_node_helper_userlevel_neg(CuTest *); void test_cil_build_ast_node_helper_userrange(CuTest *); void test_cil_build_ast_node_helper_userrange_neg(CuTest *); void test_cil_build_ast_node_helper_type(CuTest *); void test_cil_build_ast_node_helper_type_neg(CuTest *); void test_cil_build_ast_node_helper_typeattribute(CuTest *); void test_cil_build_ast_node_helper_typeattribute_neg(CuTest *); void test_cil_build_ast_node_helper_boolif(CuTest *); void test_cil_build_ast_node_helper_boolif_neg(CuTest *); void test_cil_build_ast_node_helper_tunif(CuTest *); void test_cil_build_ast_node_helper_tunif_neg(CuTest *); void test_cil_build_ast_node_helper_condblock_true(CuTest *); void test_cil_build_ast_node_helper_condblock_true_neg(CuTest *); void test_cil_build_ast_node_helper_condblock_false(CuTest *); void test_cil_build_ast_node_helper_condblock_false_neg(CuTest *); void test_cil_build_ast_node_helper_typealias(CuTest *); void test_cil_build_ast_node_helper_typealias_notype_neg(CuTest *); void test_cil_build_ast_node_helper_typebounds(CuTest *); void test_cil_build_ast_node_helper_typebounds_neg(CuTest *); void test_cil_build_ast_node_helper_typepermissive(CuTest *); void test_cil_build_ast_node_helper_typepermissive_neg(CuTest *); void test_cil_build_ast_node_helper_nametypetransition(CuTest *); void test_cil_build_ast_node_helper_nametypetransition_neg(CuTest *); void test_cil_build_ast_node_helper_rangetransition(CuTest *); void test_cil_build_ast_node_helper_rangetransition_neg(CuTest *); void test_cil_build_ast_node_helper_typeattributeset(CuTest *); void test_cil_build_ast_node_helper_typeattributeset_neg(CuTest *); void test_cil_build_ast_node_helper_userbounds(CuTest *); void test_cil_build_ast_node_helper_userbounds_neg(CuTest *); void test_cil_build_ast_node_helper_role(CuTest *); void test_cil_build_ast_node_helper_role_neg(CuTest *); void test_cil_build_ast_node_helper_roletransition(CuTest *); void test_cil_build_ast_node_helper_roletransition_neg(CuTest *); void test_cil_build_ast_node_helper_roleallow(CuTest *); void test_cil_build_ast_node_helper_roleallow_neg(CuTest *); void test_cil_build_ast_node_helper_rolebounds(CuTest *); void test_cil_build_ast_node_helper_rolebounds_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_allow(CuTest *); void test_cil_build_ast_node_helper_avrule_allow_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_auditallow(CuTest *); void test_cil_build_ast_node_helper_avrule_auditallow_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_dontaudit(CuTest *); void test_cil_build_ast_node_helper_avrule_dontaudit_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_neverallow(CuTest *); void test_cil_build_ast_node_helper_avrule_neverallow_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_transition(CuTest *); void test_cil_build_ast_node_helper_type_rule_transition_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_change(CuTest *); void test_cil_build_ast_node_helper_type_rule_change_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_member(CuTest *); void test_cil_build_ast_node_helper_type_rule_member_neg(CuTest *); void test_cil_build_ast_node_helper_bool(CuTest *); void test_cil_build_ast_node_helper_bool_neg(CuTest *); void test_cil_build_ast_node_helper_bool_tunable(CuTest *); void test_cil_build_ast_node_helper_bool_tunable_neg(CuTest *); void test_cil_build_ast_node_helper_else(CuTest *); void test_cil_build_ast_node_helper_else_neg(CuTest *); void test_cil_build_ast_node_helper_sensitivity(CuTest *); void test_cil_build_ast_node_helper_sensitivity_neg(CuTest *); void test_cil_build_ast_node_helper_sensalias(CuTest *); void test_cil_build_ast_node_helper_sensalias_neg(CuTest *); void test_cil_build_ast_node_helper_category(CuTest *); void test_cil_build_ast_node_helper_category_neg(CuTest *); void test_cil_build_ast_node_helper_catset(CuTest *tc); void test_cil_build_ast_node_helper_catset_neg(CuTest *tc); void test_cil_build_ast_node_helper_catorder(CuTest *tc); void test_cil_build_ast_node_helper_catorder_neg(CuTest *tc); void test_cil_build_ast_node_helper_catalias(CuTest *tc); void test_cil_build_ast_node_helper_catalias_neg(CuTest *tc); void test_cil_build_ast_node_helper_catrange(CuTest *tc); void test_cil_build_ast_node_helper_catrange_neg(CuTest *tc); void test_cil_build_ast_node_helper_roletype(CuTest *tc); void test_cil_build_ast_node_helper_roletype_neg(CuTest *tc); void test_cil_build_ast_node_helper_userrole(CuTest *tc); void test_cil_build_ast_node_helper_userrole_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_classcommon(CuTest *tc); void test_cil_build_ast_node_helper_gen_classcommon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_dominance(CuTest *tc); void test_cil_build_ast_node_helper_gen_dominance_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_senscat(CuTest *tc); void test_cil_build_ast_node_helper_gen_senscat_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_level(CuTest *tc); void test_cil_build_ast_node_helper_gen_level_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_levelrange(CuTest *tc); void test_cil_build_ast_node_helper_gen_levelrange_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_constrain(CuTest *tc); void test_cil_build_ast_node_helper_gen_constrain_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_mlsconstrain(CuTest *tc); void test_cil_build_ast_node_helper_gen_mlsconstrain_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_context(CuTest *tc); void test_cil_build_ast_node_helper_gen_context_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_filecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_filecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_portcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_portcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_nodecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_nodecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_genfscon(CuTest *tc); void test_cil_build_ast_node_helper_gen_genfscon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_netifcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_netifcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_pirqcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_pirqcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_iomemcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_iomemcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_ioportcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_ioportcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_pcidevicecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_pcidevicecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_fsuse(CuTest *tc); void test_cil_build_ast_node_helper_gen_fsuse_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_nested_macro_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_call(CuTest *tc); void test_cil_build_ast_node_helper_gen_call_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_optional(CuTest *tc); void test_cil_build_ast_node_helper_gen_optional_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_policycap(CuTest *tc); void test_cil_build_ast_node_helper_gen_policycap_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_ipaddr(CuTest *tc); void test_cil_build_ast_node_helper_gen_ipaddr_neg(CuTest *tc); void test_cil_build_ast_node_helper_extraargsnull_neg(CuTest *); void test_cil_build_ast_last_child_helper(CuTest *); void test_cil_build_ast_last_child_helper_extraargsnull_neg(CuTest *); #endif libsepol/cil/test/unit/test_cil_copy_ast.c0100644 0000000 0000000 00000232371 13756670065 020025 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "../../src/cil_copy_ast.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_resolve_ast.h" #define CIL_TEST_SYM_SIZE 1 int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args); struct cil_args_copy { struct cil_tree_node *dest; struct cil_db *db; }; struct cil_args_copy *gen_copy_args(struct cil_tree_node *node, struct cil_db *db) { struct cil_args_copy *args = cil_malloc(sizeof(*args)); args->dest = node; args->db = db; return args; } void test_cil_copy_list(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc =cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); } void test_cil_copy_list_sublist(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertStrEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->data, ((struct cil_list *)cil_l->head->next->next->data)->head->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); CuAssertIntEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->flavor, ((struct cil_list *)cil_l->head->next->next->data)->head->flavor); } void test_cil_copy_list_sublist_extra(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", "foo4", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertStrEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->data, ((struct cil_list *)cil_l->head->next->next->data)->head->data); CuAssertStrEquals(tc, copy_list->head->next->next->next->data, cil_l->head->next->next->next->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); CuAssertIntEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->flavor, ((struct cil_list *)cil_l->head->next->next->data)->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->next->next->flavor, cil_l->head->next->next->next->flavor); } void test_cil_copy_list_orignull_neg(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l = NULL; gen_test_tree(&test_tree, line); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_ERR); CuAssertPtrEquals(tc, copy_list->head, NULL); } void test_cil_copy_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK][CIL_SYM_BLOCKS]); int rc = cil_copy_block(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; test_ast_node->parent = new_tree_node; test_ast_node->line = 1; struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); int rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next, test_ast_node); rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next->next, test_ast_node); rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_class(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_common(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_classcommon *test_copy; cil_classcommon_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_classcommon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_classcommon *)test_ast_node->data)->class_str, test_copy->class_str); CuAssertStrEquals(tc, ((struct cil_classcommon *)test_ast_node->data)->common_str, test_copy->common_str); } void test_cil_copy_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sid(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sidcontext(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_user *)test_copy->data)->datum.name, ((struct cil_user *)test_ast_node->data)->datum.name); } void test_cil_copy_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_user(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_role(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_userrole *test_copy; cil_userrole_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_userrole(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_userrole *)test_ast_node->data)->user_str, test_copy->user_str); CuAssertStrEquals(tc, ((struct cil_userrole *)test_ast_node->data)->role_str, test_copy->role_str); } void test_cil_copy_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_type(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_typealias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_typeattribute(CuTest *tc) { char *line[] = {"(", "typettribute", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_typeattribute(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_bool(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_bool *)test_copy->data)->value, ((struct cil_bool *)test_ast_node->data)->value); } void test_cil_copy_type_rule(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); struct cil_type_rule *test_copy; cil_type_rule_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_type_rule(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->rule_kind, test_copy->rule_kind); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->src_str, test_copy->src_str); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->tgt_str, test_copy->tgt_str); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->obj_str, test_copy->obj_str); } void test_cil_copy_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); struct cil_avrule *test_copy; cil_avrule_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_avrule(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->rule_kind, test_copy->rule_kind); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->src_str, test_copy->src_str); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->tgt_str, test_copy->tgt_str); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->class_str, test_copy->classpermset->class_str); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->flavor, test_copy->classpermset->permset->perms_list_str->head->flavor); CuAssertStrEquals(tc, (char*)((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->data, (char*)test_copy->classpermset->permset->perms_list_str->head->data); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->next->flavor, test_copy->classpermset->permset->perms_list_str->head->next->flavor); CuAssertStrEquals(tc, (char*)((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->next->data, (char*)test_copy->classpermset->permset->perms_list_str->head->next->data); } void test_cil_copy_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sens(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sensalias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_sensalias *)test_copy->data)->sens_str, ((struct cil_sensalias *)test_ast_node->data)->sens_str); } void test_cil_copy_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_cat(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_catalias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_catalias *)test_copy->data)->cat_str, ((struct cil_catalias *)test_ast_node->data)->cat_str); } void test_cil_copy_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); struct cil_senscat *test_copy; cil_senscat_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_senscat(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_senscat *)test_ast_node->data)->sens_str, test_copy->sens_str); CuAssertStrEquals(tc, (char*)((struct cil_senscat *)test_ast_node->data)->catset->cat_list_str->head->data, (char*)test_copy->catset->cat_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_senscat *)test_ast_node->data)->catset->cat_list_str->head->next->data, (char*)test_copy->catset->cat_list_str->head->next->data); } void test_cil_copy_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); struct cil_catorder *test_copy; cil_catorder_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_catorder(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, (char*)((struct cil_catorder *)test_ast_node->data)->cat_list_str->head->data, (char*)test_copy->cat_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_catorder *)test_ast_node->data)->cat_list_str->head->next->data, (char*)test_copy->cat_list_str->head->next->data); } void test_cil_copy_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); struct cil_sens_dominates *test_copy; cil_sens_dominates_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_dominance(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, (char*)((struct cil_sens_dominates *)test_ast_node->data)->sens_list_str->head->data, (char*)test_copy->sens_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_sens_dominates *)test_ast_node->data)->sens_list_str->head->next->data, (char*)test_copy->sens_list_str->head->next->data); } void test_cil_copy_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_level(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_fill_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_level_init((struct cil_level**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_level((struct cil_level*)test_ast_node->data, (struct cil_level*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_level *)test_copy->data)->sens_str, ((struct cil_level *)test_ast_node->data)->sens_str); } void test_cil_copy_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_context(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_netifcon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_netifcon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->interface_str, ((struct cil_netifcon *)test_ast_node->data)->interface_str); CuAssertStrEquals(tc, test_copy->if_context_str, ((struct cil_netifcon *)test_ast_node->data)->if_context_str); CuAssertStrEquals(tc, test_copy->packet_context_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context_str); } void test_cil_copy_netifcon_nested(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_netifcon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_netifcon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->interface_str, ((struct cil_netifcon *)test_ast_node->data)->interface_str); CuAssertStrEquals(tc, test_copy->if_context_str, ((struct cil_netifcon *)test_ast_node->data)->if_context_str); CuAssertStrEquals(tc, test_copy->packet_context_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context_str); CuAssertStrEquals(tc, test_copy->packet_context->user_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->user_str); CuAssertStrEquals(tc, test_copy->packet_context->role_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->role_str); CuAssertStrEquals(tc, test_copy->packet_context->type_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->type_str); CuAssertStrEquals(tc, test_copy->packet_context->range_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->range_str); } void test_cil_copy_fill_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "range", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_context_init((struct cil_context**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_context((struct cil_context*)test_ast_node->data, (struct cil_context*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->user_str, ((struct cil_context *)test_ast_node->data)->user_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->role_str, ((struct cil_context *)test_ast_node->data)->role_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->type_str, ((struct cil_context *)test_ast_node->data)->type_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->range_str, ((struct cil_context *)test_ast_node->data)->range_str); } void test_cil_copy_fill_context_anonrange(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_context_init((struct cil_context**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_context((struct cil_context*)test_ast_node->data, (struct cil_context*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->user_str, ((struct cil_context *)test_ast_node->data)->user_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->role_str, ((struct cil_context *)test_ast_node->data)->role_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->type_str, ((struct cil_context *)test_ast_node->data)->type_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->range_str, ((struct cil_context *)test_ast_node->data)->range_str); } void test_cil_copy_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_call *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_call(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->macro_str, ((struct cil_call *)test_ast_node->data)->macro_str); } void test_cil_copy_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_optional(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_nodecon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_nodecon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->addr_str, ((struct cil_nodecon *)test_ast_node->data)->addr_str); CuAssertStrEquals(tc, test_copy->mask_str, ((struct cil_nodecon *)test_ast_node->data)->mask_str); CuAssertStrEquals(tc, test_copy->context_str, ((struct cil_nodecon *)test_ast_node->data)->context_str); } void test_cil_copy_nodecon_anon(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "(", "192.168.1.1", ")", "(", "user", "role", "type", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_nodecon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_nodecon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->addr_str, ((struct cil_nodecon *)test_ast_node->data)->addr_str); CuAssertStrEquals(tc, test_copy->mask_str, ((struct cil_nodecon *)test_ast_node->data)->mask_str); CuAssertStrEquals(tc, test_copy->context_str, ((struct cil_nodecon *)test_ast_node->data)->context_str); } void test_cil_copy_fill_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); struct cil_ipaddr *new; cil_ipaddr_init(&new); struct cil_ipaddr *old; cil_ipaddr_init(&new); old = (struct cil_ipaddr*)test_ast_node->data; int rc = cil_copy_fill_ipaddr(old, new); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, old->family, new->family); } void test_cil_copy_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_ipaddr(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_conditional(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_list_item *curr_old; curr_old = ((struct cil_booleanif*)test_ast_node->data)->expr_stack->head; struct cil_conditional *cond_new; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_conditional(test_db, curr_old->data, (void**)&cond_new, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_conditional*)curr_old->data)->str, cond_new->str); CuAssertIntEquals(tc, ((struct cil_conditional*)curr_old->data)->flavor, cond_new->flavor); } void test_cil_copy_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_booleanif *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_boolif(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_constrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_constrain *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_constrain(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_constrain*)test_copy)->classpermset->class_str, ((struct cil_constrain *)test_ast_node->data)->classpermset->class_str); } /* void test_cil_copy_ast(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_constrain *test_copy; cil_constrain_init(&test_copy); cil_list_init(&test_copy->expr); int rc = cil_copy_ast(((struct cil_constrain *)test_ast_node->data)->expr, test_copy->expr); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_ast_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_constrain *test_copy; cil_constrain_init(&test_copy); cil_list_init(&test_copy->expr); int rc = cil_copy_ast(((struct cil_constrain *)test_ast_node->data)->expr, test_copy->expr); CuAssertIntEquals(tc, rc, SEPOL_ERR); } */ /* node_helper functions */ void test_cil_copy_node_helper_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_block_merge(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_class *test_class; cil_class_init(&test_class); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_CLASS; parent_node->data = test_class; struct cil_tree_node *root; cil_tree_node_init(&root); root->flavor = CIL_ROOT; parent_node->parent = root; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_class_dup_neg(CuTest *tc) { char *line[] = {"(", "class", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_common_dup_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sid_merge(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_user_merge(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_role_merge(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type_merge(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typeattribute_merge(CuTest *tc) { char *line[] = {"(", "typeattribute", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typealias_dup_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_bool_dup_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "file", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type_rule(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sens_merge(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sensalias_dup_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_cat_merge(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catalias_dup_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_senscat *test_senscat; cil_senscat_init(&test_senscat); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_SENSCAT; parent_node->data = test_senscat; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_catorder *test_catorder; cil_catorder_init(&test_catorder); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_CATORDER; parent_node->data = test_catorder; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_sens *test_sens; cil_sens_init(&test_sens); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_SENS; parent_node->data = test_sens; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_level_dup_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_context_dup_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_optional_merge(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_ipaddr_dup_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_mlsconstrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_orignull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); struct cil_args_copy *extra_args = NULL; uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol/cil/test/unit/test_cil_copy_ast.h0100644 0000000 0000000 00000014713 13756670065 020030 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_COPY_AST_H_ #define TEST_CIL_COPY_AST_H_ #include "CuTest.h" void test_cil_copy_list(CuTest *); void test_cil_copy_list_sublist(CuTest *); void test_cil_copy_list_sublist_extra(CuTest *); void test_cil_copy_list_orignull_neg(CuTest *); void test_cil_copy_block(CuTest *); void test_cil_copy_node_helper_block(CuTest *tc); void test_cil_copy_node_helper_block_merge(CuTest *tc); void test_cil_copy_perm(CuTest *); void test_cil_copy_node_helper_perm(CuTest *tc); void test_cil_copy_node_helper_perm_neg(CuTest *tc); void test_cil_copy_class(CuTest *); void test_cil_copy_node_helper_class(CuTest *tc); void test_cil_copy_node_helper_class_dup_neg(CuTest *tc); void test_cil_copy_common(CuTest *); void test_cil_copy_node_helper_common(CuTest *tc); void test_cil_copy_node_helper_common_dup_neg(CuTest *tc); void test_cil_copy_classcommon(CuTest *); void test_cil_copy_node_helper_classcommon(CuTest *tc); void test_cil_copy_sid(CuTest *); void test_cil_copy_node_helper_sid(CuTest *tc); void test_cil_copy_node_helper_sid_merge(CuTest *tc); void test_cil_copy_sidcontext(CuTest *); void test_cil_copy_node_helper_sidcontext(CuTest *tc); void test_cil_copy_user(CuTest *); void test_cil_copy_node_helper_user(CuTest *tc); void test_cil_copy_node_helper_user_merge(CuTest *tc); void test_cil_copy_role(CuTest *); void test_cil_copy_node_helper_role(CuTest *tc); void test_cil_copy_node_helper_role_merge(CuTest *tc); void test_cil_copy_userrole(CuTest *); void test_cil_copy_node_helper_userrole(CuTest *tc); void test_cil_copy_type(CuTest *); void test_cil_copy_node_helper_type(CuTest *tc); void test_cil_copy_node_helper_type_merge(CuTest *tc); void test_cil_copy_typeattribute(CuTest *); void test_cil_copy_node_helper_typeattribute(CuTest *tc); void test_cil_copy_node_helper_typeattribute_merge(CuTest *tc); void test_cil_copy_typealias(CuTest *); void test_cil_copy_node_helper_typealias(CuTest *tc); void test_cil_copy_node_helper_typealias_dup_neg(CuTest *tc); void test_cil_copy_bool(CuTest *); void test_cil_copy_node_helper_bool(CuTest *tc); void test_cil_copy_node_helper_bool_dup_neg(CuTest *tc); void test_cil_copy_avrule(CuTest *); void test_cil_copy_node_helper_avrule(CuTest *tc); void test_cil_copy_type_rule(CuTest *); void test_cil_copy_node_helper_type_rule(CuTest *tc); void test_cil_copy_sens(CuTest *); void test_cil_copy_node_helper_sens(CuTest *tc); void test_cil_copy_node_helper_sens_merge(CuTest *tc); void test_cil_copy_sensalias(CuTest *); void test_cil_copy_node_helper_sensalias(CuTest *tc); void test_cil_copy_node_helper_sensalias_dup_neg(CuTest *tc); void test_cil_copy_cat(CuTest *); void test_cil_copy_node_helper_cat(CuTest *tc); void test_cil_copy_node_helper_cat_merge(CuTest *tc); void test_cil_copy_catalias(CuTest *); void test_cil_copy_node_helper_catalias(CuTest *tc); void test_cil_copy_node_helper_catalias_dup_neg(CuTest *tc); void test_cil_copy_senscat(CuTest *); void test_cil_copy_node_helper_senscat(CuTest *tc); void test_cil_copy_catorder(CuTest *); void test_cil_copy_node_helper_catorder(CuTest *tc); void test_cil_copy_dominance(CuTest *); void test_cil_copy_node_helper_dominance(CuTest *tc); void test_cil_copy_level(CuTest *); void test_cil_copy_node_helper_level(CuTest *tc); void test_cil_copy_node_helper_level_dup_neg(CuTest *tc); void test_cil_copy_fill_level(CuTest *); void test_cil_copy_context(CuTest *); void test_cil_copy_node_helper_context(CuTest *tc); void test_cil_copy_node_helper_context_dup_neg(CuTest *tc); void test_cil_copy_netifcon(CuTest *); void test_cil_copy_netifcon_nested(CuTest *); void test_cil_copy_node_helper_netifcon(CuTest *tc); void test_cil_copy_node_helper_netifcon_merge(CuTest *tc); void test_cil_copy_fill_context(CuTest *); void test_cil_copy_fill_context_anonrange(CuTest *); void test_cil_copy_call(CuTest *); void test_cil_copy_node_helper_call(CuTest *tc); void test_cil_copy_optional(CuTest *); void test_cil_copy_node_helper_optional(CuTest *tc); void test_cil_copy_node_helper_optional_merge(CuTest *tc); void test_cil_copy_nodecon(CuTest *); void test_cil_copy_nodecon_anon(CuTest *); void test_cil_copy_fill_ipaddr(CuTest *); void test_cil_copy_ipaddr(CuTest *); void test_cil_copy_node_helper_ipaddr(CuTest *tc); void test_cil_copy_node_helper_ipaddr_dup_neg(CuTest *tc); void test_cil_copy_conditional(CuTest *); void test_cil_copy_boolif(CuTest *); void test_cil_copy_node_helper_boolif(CuTest *tc); void test_cil_copy_constrain(CuTest *); void test_cil_copy_node_helper_mlsconstrain(CuTest *tc); void test_cil_copy_ast(CuTest *); void test_cil_copy_ast_neg(CuTest *); void test_cil_copy_node_helper_orignull_neg(CuTest *tc); void test_cil_copy_node_helper_extraargsnull_neg(CuTest *tc); void test_cil_copy_data_helper(CuTest *tc); void test_cil_copy_data_helper_getparentsymtab_neg(CuTest *tc); void test_cil_copy_data_helper_duplicatedb_neg(CuTest *tc); #endif libsepol/cil/test/unit/test_cil_fqn.c0100644 0000000 0000000 00000005520 13756670065 016762 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_fqn.h" #include "../../src/cil_build_ast.h" void test_cil_qualify_name(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "sid", "test", "con", NULL}; struct cil_tree *tree; gen_test_tree(&tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, tree->root, test_db->ast->root); int rc = cil_fqn_qualify(test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_qualify_name_cil_flavor(CuTest *tc) { char *line[] = {"(", "class", "file", "inherits", "file", "(", "open", ")", ")", NULL}; struct cil_tree *tree; gen_test_tree(&tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, tree->root, test_db->ast->root); int rc = cil_fqn_qualify(test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } libsepol/cil/test/unit/test_cil_fqn.h0100644 0000000 0000000 00000003362 13756670065 016771 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_FQN_H_ #define TEST_CIL_FQN_H_ #include "CuTest.h" void test_cil_qualify_name(CuTest *); void test_cil_qualify_name_cil_flavor(CuTest *tc); #endif libsepol/cil/test/unit/test_cil_lexer.c0100644 0000000 0000000 00000006732 13756670065 017323 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_lexer.h" #include "../../src/cil_lexer.h" void test_cil_lexer_setup(CuTest *tc) { char *test_str = "(test \"qstring\");comment\n"; uint32_t str_size = strlen(test_str); char *buffer = malloc(str_size + 2); memset(buffer+str_size, 0, 2); strncpy(buffer, test_str, str_size); int rc = cil_lexer_setup(buffer, str_size + 2); CuAssertIntEquals(tc, SEPOL_OK, rc); free(buffer); } void test_cil_lexer_next(CuTest *tc) { char *test_str = "(test \"qstring\") ;comment\n"; uint32_t str_size = strlen(test_str); char *buffer = malloc(str_size + 2); memset(buffer+str_size, 0, 2); strcpy(buffer, test_str); cil_lexer_setup(buffer, str_size + 2); struct token test_tok; int rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, OPAREN, test_tok.type); CuAssertStrEquals(tc, "(", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SYMBOL, test_tok.type); CuAssertStrEquals(tc, "test", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, QSTRING, test_tok.type); CuAssertStrEquals(tc, "\"qstring\"", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CPAREN, test_tok.type); CuAssertStrEquals(tc, ")", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, COMMENT, test_tok.type); CuAssertStrEquals(tc, ";comment", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); free(buffer); } libsepol/cil/test/unit/test_cil_lexer.h0100644 0000000 0000000 00000003347 13756670065 017327 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_LEXER_H_ #define TEST_CIL_LEXER_H_ #include "CuTest.h" void test_cil_lexer_setup(CuTest *); void test_cil_lexer_next(CuTest *); #endif libsepol/cil/test/unit/test_cil_list.c0100644 0000000 0000000 00000025607 13756670065 017161 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "../../src/cil_build_ast.h" void test_cil_list_init(CuTest *tc) { struct cil_avrule *test_avrule = malloc(sizeof(*test_avrule)); cil_classpermset_init(&test_avrule->classpermset); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); CuAssertPtrNotNull(tc, test_avrule->classpermset->permset->perms_list_str); cil_destroy_avrule(test_avrule); } void test_cil_list_append_item(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_append_item_append(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; int rc2 = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_list_append_item_append_extra(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", "process", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; int rc2 = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next->next; int rc3 = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_list_append_item_listnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list = NULL; struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_append_item_itemnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item = NULL; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_prepend_item_prepend(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_prepend_item_prepend_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", "process", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; struct cil_list_item *test_new_item_next; cil_list_item_init(&test_new_item_next); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; test_new_item->next = test_new_item_next; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item_listnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list = NULL; struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item_itemnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item = NULL; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol/cil/test/unit/test_cil_list.h0100644 0000000 0000000 00000004236 13756670065 017161 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_LIST_H_ #define TEST_CIL_LIST_H_ #include "CuTest.h" void test_cil_list_item_init(CuTest *); void test_cil_list_append_item(CuTest *); void test_cil_list_append_item_append(CuTest *); void test_cil_list_append_item_append_extra(CuTest *); void test_cil_list_append_item_listnull_neg(CuTest *); void test_cil_list_append_item_itemnull_neg(CuTest *); void test_cil_list_prepend_item_prepend(CuTest *); void test_cil_list_prepend_item_prepend_neg(CuTest *); void test_cil_list_prepend_item_listnull_neg(CuTest *); void test_cil_list_prepend_item_itemnull_neg(CuTest *); #endif libsepol/cil/test/unit/test_cil_parser.c0100644 0000000 0000000 00000004360 13756670065 017473 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_parser.h" #include "../../src/cil_parser.h" #include "../../src/cil_internal.h" // TODO rewrite to use the gen_tree function void test_cil_parser(CuTest *tc) { int rc = 0; struct cil_file_data *data; struct cil_tree *test_parse_root; cil_tree_init(&test_parse_root); struct cil_db *test_db; cil_db_init(&test_db); set_cil_file_data(&data); rc = cil_parser("policy.cil", data->buffer, data->file_size + 2, &test_parse_root); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_parse_root); // TODO add checking of the parse tree that is returned } libsepol/cil/test/unit/test_cil_parser.h0100644 0000000 0000000 00000003300 13756670065 017471 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_PARSER_H_ #define TEST_CIL_PARSER_H_ #include "CuTest.h" void test_cil_parser(CuTest *); #endif libsepol/cil/test/unit/test_cil_post.c0100644 0000000 0000000 00000050666 13756670065 017176 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_post.h" #include "../../src/cil_post.h" #include "../../src/cil_internal.h" void test_cil_post_filecon_compare_meta_a_not_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "ba.r"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_meta_b_not_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "bar"; afilecon->path_str = "foo"; bfilecon->root_str = "ba.rr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; bfilecon->root_str = ".?"; bfilecon->path_str = "."; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_type_atype_greater_btype(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_CHAR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_DIR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_type_btype_greater_atype(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_DIR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_CHAR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "."; afilecon->path_str = "."; bfilecon->root_str = ".*+|[({"; bfilecon->path_str = "."; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_stemlen_a_greater_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "bar"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_stemlen_b_greater_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "barre"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_equal(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_DIR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_DIR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertIntEquals(tc, 0, rc); } void test_cil_post_portcon_compare_atotal_greater_btotal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 15; aportcon->port_high = 30; bportcon->port_low = 10; bportcon->port_high = 11; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_portcon_compare_btotal_greater_atotal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 5; aportcon->port_high = 5; bportcon->port_low = 11; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_portcon_compare_aportlow_greater_bportlow(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 30; aportcon->port_high = 33; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_portcon_compare_bportlow_greater_aportlow(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 5; aportcon->port_high = 8; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_portcon_compare_equal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 17; aportcon->port_high = 20; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc == 0); } void test_cil_post_genfscon_compare_atypestr_greater_btypestr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "aaaa"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc < 0); } void test_cil_post_genfscon_compare_btypestr_greater_atypestr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "aaaa"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc > 0); } void test_cil_post_genfscon_compare_apathstr_greater_bpathstr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "aaaa"; agenfscon->path_str = "ff"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "aaaa"; bgenfscon->path_str = "gg"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc < 0); } void test_cil_post_genfscon_compare_bpathstr_greater_apathstr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; agenfscon->path_str = "cccc"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; bgenfscon->path_str = "aaaa"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc > 0); } void test_cil_post_genfscon_compare_equal(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; agenfscon->path_str = "cccc"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; bgenfscon->path_str = "cccc"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertIntEquals(tc, 0, rc); } void test_cil_post_netifcon_compare_a_greater_b(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "aaa"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "bbb"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_netifcon_compare_b_greater_a(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "bbb"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "aaa"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_netifcon_compare_equal(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "aaa"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "aaa"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc == 0); } void test_cil_post_nodecon_compare_aipv4_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_aipv6_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv4_lessthan_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 99; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 101; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 99; anodecon->mask->ip.v4.s_addr = 99; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '5'; anodecon->mask->ip.v6.s6_addr[0] = '9'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '3'; bnodecon->mask->ip.v6.s6_addr[0] = '9'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv6_lessthan_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '3'; anodecon->mask->ip.v6.s6_addr[0] = '1'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '5'; bnodecon->mask->ip.v6.s6_addr[0] = '1'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '1'; anodecon->mask->ip.v6.s6_addr[0] = '4'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '1'; bnodecon->mask->ip.v6.s6_addr[0] = '3'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '5'; anodecon->mask->ip.v6.s6_addr[0] = '1'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '5'; bnodecon->mask->ip.v6.s6_addr[0] = '6'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_type_a_greater_b(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_TASK; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc < 0); } void test_cil_post_fsuse_compare_type_b_greater_a(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_TASK; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_fsstr_a_greater_b(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "aaa"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "bbb"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc < 0); } void test_cil_post_fsuse_compare_fsstr_b_greater_a(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "bbb"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "aaa"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_equal(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "foo"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "foo"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc == 0); } libsepol/cil/test/unit/test_cil_post.h0100644 0000000 0000000 00000010170 13756670065 017165 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_POLICY_H_ #define TEST_CIL_POLICY_H_ #include "CuTest.h" void test_cil_post_filecon_compare_meta_a_not_b(CuTest *tc); void test_cil_post_filecon_compare_meta_b_not_a(CuTest *tc); void test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b(CuTest *tc); void test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a(CuTest *tc); void test_cil_post_filecon_compare_type_atype_greater_btype(CuTest *tc); void test_cil_post_filecon_compare_type_btype_greater_atype(CuTest *tc); void test_cil_post_filecon_compare_stemlen_a_greater_b(CuTest *tc); void test_cil_post_filecon_compare_stemlen_b_greater_a(CuTest *tc); void test_cil_post_filecon_compare_equal(CuTest *tc); void test_cil_post_portcon_compare_atotal_greater_btotal(CuTest *tc); void test_cil_post_portcon_compare_btotal_greater_atotal(CuTest *tc); void test_cil_post_portcon_compare_aportlow_greater_bportlow(CuTest *tc); void test_cil_post_portcon_compare_bportlow_greater_aportlow(CuTest *tc); void test_cil_post_portcon_compare_equal(CuTest *tc); void test_cil_post_genfscon_compare_atypestr_greater_btypestr(CuTest *tc); void test_cil_post_genfscon_compare_btypestr_greater_atypestr(CuTest *tc); void test_cil_post_genfscon_compare_apathstr_greater_bpathstr(CuTest *tc); void test_cil_post_genfscon_compare_bpathstr_greater_apathstr(CuTest *tc); void test_cil_post_genfscon_compare_equal(CuTest *tc); void test_cil_post_netifcon_compare_a_greater_b(CuTest *tc); void test_cil_post_netifcon_compare_b_greater_a(CuTest *tc); void test_cil_post_netifcon_compare_equal(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_lessthan_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_lessthan_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6(CuTest *tc); void test_cil_post_fsuse_compare_type_a_greater_b(CuTest *tc); void test_cil_post_fsuse_compare_type_b_greater_a(CuTest *tc); void test_cil_post_fsuse_compare_fsstr_a_greater_b(CuTest *tc); void test_cil_post_fsuse_compare_fsstr_b_greater_a(CuTest *tc); void test_cil_post_fsuse_compare_equal(CuTest *tc); #endif libsepol/cil/test/unit/test_cil_resolve_ast.c0100644 0000000 0000000 00001422552 13756670065 020535 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_resolve_ast.h" #include "../../src/cil_verify.h" #include "../../src/cil_internal.h" /* this all needs to be moved to a private header file */ int __cil_resolve_ast_node_helper(struct cil_tree_node *, uint32_t *, void *); int __cil_disable_children_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *); struct cil_args_resolve { struct cil_db *db; enum cil_pass pass; uint32_t *changed; struct cil_tree_node *callstack; struct cil_tree_node *optstack; struct cil_tree_node *macro; }; struct cil_args_resolve *gen_resolve_args(struct cil_db *db, enum cil_pass pass, uint32_t *changed, struct cil_tree_node *calls, struct cil_tree_node *opts, struct cil_tree_node *macro) { struct cil_args_resolve *args = cil_malloc(sizeof(*args)); args->db = db; args->pass = pass; args->changed = changed; args->callstack = calls; args->optstack = opts; args->macro = macro; return args; } void test_cil_resolve_name(CuTest *tc) { char *line[] = { "(", "block", "foo", "(", "typealias", "test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_curr = test_db->ast->root->cl_head->cl_head; struct cil_typealias *test_alias = (struct cil_typealias*)test_curr->data; struct cil_tree_node *type_node = NULL; int rc = cil_resolve_name(test_curr, test_alias->type_str, CIL_SYM_TYPES, args, &type_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_invalid_type_neg(CuTest *tc) { char *line[] = { "(", "block", "foo", "(", "typealias", "foo.test2", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_curr = test_db->ast->root->cl_head->cl_head; struct cil_typealias *test_alias = (struct cil_typealias*)test_curr->data; struct cil_tree_node *type_node = NULL; int rc = cil_resolve_name(test_curr, test_alias->type_str, CIL_SYM_TYPES, args, &type_node); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_curr_null_neg(CuTest *tc) { struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_resolve_ast(test_db, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } /* cil_resolve test cases */ void test_cil_resolve_roleallow(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roleallow_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc1=cil_build_ast(test_db, test_tree->root, test_db->ast->root); rc1 = rc1; int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roleallow_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "file", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classmapping_anon_inmacro(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next; int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_classmapping_anon_inmacro_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "DNE", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next; int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_classmapping_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classmapping_named_classmapname_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon_classmapname_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "dne", "read", "(", "file", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon_permset_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "dne", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rolebounds(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rolebounds_exists_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_rolebounds_role1_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role_DNE", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rolebounds_role2_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role_DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_sensalias(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sensalias_sensdecl_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_sensalias(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catalias(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catalias(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catalias_catdecl_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catalias(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c3", ")", "(", "categoryorder", "(", "c0", "c3", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); int rc = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); int rc2 = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_catorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c3", ")", "(", "categoryorder", "(", "c5", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); int rc = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); int rc2 = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s6", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_cat_list(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_cat_list_catlistnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; test_catset->cat_list_str = NULL; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_rescatlistnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list = NULL; struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_cat_list_catrange_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c2", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MLS; struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_catname_neg(CuTest *tc) { char *line[] = {"(", "category", "c5", ")", "(", "category", "c6", ")", "(", "category", "c7", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MLS; struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, test_catset, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catset_catlist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", "c4", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, test_catset, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catrange_catloworder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); test_db->catorder->head = test_db->catorder->head->next; test_db->catorder->head->next = NULL; args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_catrange_cathighorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c255", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_catrange_cat1_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c12", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catrange_cat2_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c23", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_catrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "categoryorder", "(", "c0", "c255", "c500", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c255", "c5", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MLS; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_senscat_catsetname(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "categoryset", "foo", "(", "c0", "c255", "c500", ")", ")", "(", "categoryorder", "(", "c0", "c255", "c500", ")", ")", "(", "sensitivitycategory", "s1", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->next->next->data; cil_resolve_catset(test_db->ast->root->cl_head->next->next->next->next->next, test_catset, args); args->pass = CIL_PASS_MISC2; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_catsetname_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "sensitivitycategory", "s1", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_sublist(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c1", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c1", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_missingsens_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_category_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c5", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_currrangecat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c1", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c1", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MISC2; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_level_catlist(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "categoryorder", "(", "c0", "c1", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", "c1", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", "c1", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", "c1", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "cats", "(", "c0", "c1", "c2", ")", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "cats", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "cats", ")", ")", "(", "level", "high", "(", "s0", "(", "cats", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); struct cil_catset *cs = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_MLS; cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, cs, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level_catset_name_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "cats", "(", "c0", "c1", "c2", ")", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "cats", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "dne", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_level_sens_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s1", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s1", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_ENOENT, rc2); } void test_cil_resolve_level_cat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c1", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_ENOENT, rc2); } void test_cil_resolve_level_senscat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s1", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, SEPOL_ERR, rc2); } void test_cil_resolve_levelrange_namedlvl(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_levelrange_namedlvl_low_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_namedlvl_high_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_anonlvl(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_levelrange_anonlvl_low_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "DNE", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_anonlvl_high_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "dne", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_constrain_class_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "foo", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain_perm_resolve_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "foo", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_context_macro(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", ")", "(", "call", "mm", "(", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head->data; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_context_macro_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", ")", "(", "call", "mm", "(", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "DNE", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head->data; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_context_namedrange(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_context_namedrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_user_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_role_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_type_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_anon_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roletransition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_type_in_multiple_attrs(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attrs2", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs2", "type_t", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next->next, args); int rc2 = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_typeattributeset_multiple_excludes_with_not(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attrs2", ")", "(", "type", "type_t", ")", "(", "type", "type_b", ")", "(", "type", "type_a", ")", "(", "typeattributeset", "attrs", "(", "and", "type_a", "type_b", ")", ")", "(", "typeattributeset", "attrs2", "(", "not", "attrs", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_multiple_types_with_and(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "type_tt", ")", "(", "typeattributeset", "attrs", "(", "and", "type_t", "type_tt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_using_attr(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attr_a", ")", "(", "typeattributeset", "attrs", "attr_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_name_neg(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_undef_type_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_not(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "t_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_undef_type_not_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typealias(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo.test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typealias(test_db->ast->root->cl_head->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typealias_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo", "apache_alias", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typealias(test_db->ast->root->cl_head->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typebounds(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typebounds_repeatbind_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next, args); int rc2 = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_ERR, rc2); } void test_cil_resolve_typebounds_type1_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typebounds_type2_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typepermissive(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typepermissive(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typepermissive(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nametypetransition_src_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "wrong", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_tgt_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "wrong", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_class_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "wrong", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_dest_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "wrong", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_namedrange_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "l", ")", ")", "(", "call", "mm", "(", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_namedrange_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "l", ")", ")", "(", "call", "mm", "(", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_namedrange(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "foo_range", "(", "low", "high", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "foo_range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_namedrange_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "foo_range", "(", "low", "high", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_type1_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_DNE", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_type2_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_DNE", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_class_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_DNE", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_call_level_l_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "l", "high", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_l_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "l", "high", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c4", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_h_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "h", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "h", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_h_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "h", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "h", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c4", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_level_l_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low_DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_level_h_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high_DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_anon_level_l(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "(", "s0", "(", "c0", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_anon_level_l_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "(", "s0", "(", "c_DNE", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_anon_level_h(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_anon_level_h_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "(", "s_DNE", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classcommon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "common", "file", "(", "write", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classcommon_no_class_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "classcommon", "foo", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classcommon_no_common_neg(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "read", ")", ")", "(", "classcommon", "foo", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_named_namedpermlist(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "baz", ")", ")", "(", "permissionset", "baz", "(", "read", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_named_permlist_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "dne", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classpermset_named_unnamedcps_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "(", "read", ")", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_anon_namedpermlist(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "baz", ")", ")", "(", "permissionset", "baz", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_anon_permlist_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "(", "dne", ")", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_avrule_permset(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "write", ")", ")", "(", "allow", "test", "foo", "(", "bar", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_avrule_permset_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "close", ")", ")", "(", "allow", "test", "foo", "(", "bar", "dne", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_permset_permdne_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "dne", ")", ")", "(", "allow", "test", "foo", "(", "bar", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_firsttype_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "fail1", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_secondtype_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "fail2", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_class_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "fail3", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "execute", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_transition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_change_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_member_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_filecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_filecon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_filecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "filecon", "root", "path", "file", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_filecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "filecon", "root", "path", "file", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_portcon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_portcon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_portcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "portcon", "udp", "25", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_portcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "portcon", "udp", "25", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_genfscon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_genfscon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_genfscon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "genfscon", "type", "path", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_genfscon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "genfscon", "type", "path", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "ipaddr", "netmask", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonipaddr_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "(", "192.168.1.1", ")", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonnetmask_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "(", "192.168.1.1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonipaddr_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "netmask", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "(", "2001:0DB8:AC10:FE01::", ")", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonnetmask_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "(", "2001:0DB8:AC10:FE01::", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_diffipfam_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "(", "192.168.1.1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_nodecon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "n", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "n", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_netmask_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_netifcon_otf_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_interface_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_unnamed(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_netifcon_unnamed_packet_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_unnamed_otf_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "foo_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_sublist_secondlist_missing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pirqcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "pirqcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_iomemcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_iomemcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_iomemcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "iomemcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_iomemcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ioportcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ioportcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ioportcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ioportcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ioportcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pcidevicecon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pcidevicecon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pcidevicecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "pcidevicecon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pcidevicecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_fsuse(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_fsuse_nocontext_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_fsuse_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_fsuse_anon(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "fsuse", "xattr", "ext3", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_fsuse_anon_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "fsuse", "xattr", "ext3", "(", "system_uu", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sidcontext(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_levels(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_level(level, (struct cil_level*)level->data, args); cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_context(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *context = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_context(context, (struct cil_context*)context->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_context_wrongname_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *context = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_context(context, (struct cil_context*)context->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sidcontext_named_context_invaliduser_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_blockinherit(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "b", ")", ")", "(", "block", "foo", "(", "type", "a", ")", "(", "blockinherit", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_blockinherit(test_db->ast->root->cl_head->next->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_blockinherit_blockstrdne_neg(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "b", ")", ")", "(", "block", "foo", "(", "type", "a", ")", "(", "blockinherit", "dne", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_blockinherit(test_db->ast->root->cl_head->next->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_in_block(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", ")", ")", "(", "block", "foo", "(", "type", "a", ")", ")", "(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_in_blockstrdne_neg(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", ")", ")", "(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_in_macro(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", "write", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "allow", "foo", "bar", "(", "file", "(", "write", ")", ")", ")", ")", "(", "in", "mm", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_in_optional(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", "write", ")", ")", "(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", "(", "in", "opt", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_noparam(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", ")", ")", "(", "type", "b", ")", "(", "allow", "qaz", "b", "file", "(", "read", ")", ")", ")", "(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_type(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_user(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "sens", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "sens", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "somecats", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c0", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c5", "(", "c2", ")", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_level_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_level_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", "(", "c5", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_ipaddr(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "ipaddr", "ip", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "ip", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_ipaddr_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.168.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_ipaddr_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classmap(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmapping", "a", "read", "(", "file", "(", "open", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "open", ")", ")", "(", "type", "dead", ")", "(", "type", "bar", ")", "(", "class", "baz", "(", "close", "read", "open", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_permset_anon(CuTest *tc) { char *line[] = {"(", "type", "dead", ")", "(", "type", "bar", ")", "(", "class", "baz", "(", "close", "read", "open", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "(", "read", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "classpermissionset", "char_w", "(", "file", "(", "open", ")", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "char_w", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_anon_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknown_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; cil_resolve_name(test_db->ast->root->cl_head->next->next->next, ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro = (struct cil_macro*)macro_node->data; free(((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str); ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str = NULL; ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro->params->head->flavor = CIL_NETIFCON; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknowncall_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "m", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_call1_extraargs_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_copy_dup(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "qaz", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_missing_arg_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_paramsflavor_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; struct cil_call *new_call = ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data); cil_resolve_name(test_db->ast->root->cl_head->next->next->next, new_call->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); new_call->macro = (struct cil_macro*)macro_node->data; struct cil_list_item *item = new_call->macro->params->head; item->flavor = CIL_CONTEXT; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknownflavor_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; struct cil_call *new_call = ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data); cil_resolve_name(test_db->ast->root->cl_head->next->next->next, new_call->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); new_call->macro = (struct cil_macro*)macro_node->data; struct cil_list_item *item = new_call->macro->params->head; ((struct cil_param*)item->data)->flavor = CIL_CONTEXT; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call2_type(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_user(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "sens", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "sens", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "somecats", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_catset_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c0", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "open", ")", ")", "(", "class", "dead", "(", "close", ")", ")", "(", "class", "bar", "(", "close", ")", ")", "(", "class", "baz", "(", "close", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_permset_anon(CuTest *tc) { char *line[] = {"(", "class", "dead", "(", "close", ")", ")", "(", "class", "bar", "(", "close", ")", ")", "(", "class", "baz", "(", "close", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "(", "read", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "classpermissionset", "char_w", "(", "file", "(", "open", ")", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "char_w", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classmap(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmapping", "a", "read", "(", "file", "(", "open", ")", ")", ")", ")", "(", "call", "mm", "(", "files", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_call2_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_level_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_ipaddr(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "ipaddr", "ip", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "ip", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_ipaddr_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.168.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_unknown_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); ((struct cil_args*)((struct cil_list_item *)((struct cil_call *)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data)->args->head)->data)->flavor = CIL_SYM_UNKNOWN; args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call2_name_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "a", CIL_SYM_TYPES, &test_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_call_args_multipleparams(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data, "lvl_h", CIL_SYM_LEVELS, &test_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_call_args_diffflavor(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qaz", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_callnull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args(NULL, "qaz", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_namenull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, NULL, CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_callargsnull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qas", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_name_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node = NULL; //cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qas", CIL_TYPE, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_expr_stack_bools(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(bif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_tunables(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_type(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "type", "t1", ")", "(", "type", "type_t", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_role(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "role", "r1", ")", "(", "role", "role_r", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_user(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "user", "u1", ")", "(", "user", "user_u", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "beef", "baf", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(bif->expr_stack,test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_expr_stack_emptystr_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; ((struct cil_conditional*)bif->expr_stack->head->data)->str = NULL; int rc = cil_resolve_expr_stack(bif->expr_stack,test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_boolif(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_boolif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_boolif_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_boolif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_evaluate_expr_stack_and(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_not(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "not", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_or(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "or", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_xor(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_eq(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "eq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_neq(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "neq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_oper1(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "tunable", "baz", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "bar", "(", "jaz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_oper2(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "tunable", "baz", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "baz", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "jaz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } /* void test_cil_evaluate_expr_stack_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "neq", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); struct cil_conditional *new_cond; cil_conditional_init(&new_cond); new_cond->flavor = CIL_COND; char *baz = "baz"; new_cond->str = baz; new_cond->flavor = CIL_TUNABLE; struct cil_tunableif *tif = test_db->ast->root->cl_head->next->next->next->next->data; test_node->data = new_cond; test_node->cl_head = tif->expr_stack; tif->expr_stack->parent = test_node; cil_resolve_expr_stack(test_db, tif->expr_stack, test_db->ast->root->cl_head->next->next->next, NULL); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_ERR, rc); } */ void test_cil_resolve_tunif_false(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_tunif_true(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "true", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_tunif_resolveexpr_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } /* void test_cil_resolve_tunif_evaluateexpr_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); struct cil_conditional *new_cond; cil_conditional_init(&new_cond); new_cond->flavor = CIL_COND; char *baz = "baz"; new_cond->str = baz; new_cond->flavor = CIL_TUNABLE; struct tunableif *tif = test_db->ast->root->cl_head->next->next->next->data; test_node->data = new_cond; test_node->cl_head = tif->expr_stack; tif->expr_stack->parent = test_node; int rc = cil_resolve_tunif(test_db, test_db->ast->root->cl_head->next->next->next, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } */ void test_cil_resolve_userbounds(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userbounds_exists_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_userbounds_user1_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user_DNE", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userbounds_user2_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user_DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletype(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roletype_type_neg(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletype_role_neg(CuTest *tc) { char *line[] = {"(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrole(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrole_user_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrole_role_neg(CuTest *tc) { char *line[] = {"(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userlevel_macro(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "userlevel", "foo_u", "l", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userlevel_macro_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "userlevel", "foo_u", "l", ")", ")", "(", "call", "mm", "(", "(", "DNE", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userlevel_level_anon(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "userlevel", "foo_u", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userlevel_level_anon_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "userlevel", "foo_u", "(", "s0", "(", "DNE", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "DNE", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel_level_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrange_macro(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "userrange", "foo_u", "range", ")", ")", "(", "call", "mm", "(", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userrange_macro_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "userrange", "foo_u", "range", ")", ")", "(", "call", "mm", "(", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userrange_range_anon(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "userrange", "foo_u", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrange_range_anon_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "userrange", "foo_u", "(", "DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "DNE", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange_range_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_disable_children_helper_optional_enabled(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_optional_disabled(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; ((struct cil_optional *)test_db->ast->root->cl_head->data)->datum.state = CIL_STATE_DISABLED; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_user(CuTest *tc) { char *line[] = {"(", "user", "staff_u", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_type(CuTest *tc) { char *line[] = {"(", "type", "type_t", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_common(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_context(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_level(CuTest *tc) { char *line[] = {"(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "foo", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_tunable(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_unknown(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } /* __cil_resolve_ast_node_helper test cases */ void test_cil_resolve_ast_node_helper_call1(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call1_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "m", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call2(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call2_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_boolif_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_tunif(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c8", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s6", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roleallow(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roleallow_neg(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sensalias_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catalias_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catset_catlist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catrange_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c255", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "sensitivitycategory", "s0", "(", "c1", ")", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC2; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "sensitivitycategory", "s0", "(", "c1", ")", ")", "(", "level", "l2", "(", "s8", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_levelrange(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "dominance", "(", "s0", ")", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC2; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_levelrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "dominance", "(", "s0", ")", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "DNE", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_constrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "role", "r1", ")", "(", "role", "r2", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_constrain_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", ")", ")", "(", "class", "dir", "(", "create", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "role", "r1", ")", "(", "role", "r2", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_mlsconstrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_mlsconstrain_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "class", "dir", "(", "read", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_context(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_context_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "DNE", "high", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_senscat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s5", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "type_tt", ")", "(", "typeattributeset", "attrs", "(", "type_t", "type_tt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo.test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typealias_notype_neg(CuTest *tc) { char *line[] = {"(", "block", "bar", "(", "typealias", ".bar.test", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typebounds(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typebounds_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typepermissive(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rangetransition(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rangetransition_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_DNE", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nametypetransition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nametypetransition_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobarrr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_src_nores_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_class_nores_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_datum_null_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(","fake", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_transition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_transition_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_change(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_change_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_member(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_member_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_userbounds(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userbounds_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_roletype(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_roletype_role_neg(CuTest *tc) { char *line[] = {"(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_roletype_type_neg(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userrole_user_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrole_role_neg(CuTest *tc) { char *line[] = {"(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "DNE", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrange(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userrange_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "DNE", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_filecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_filecon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_portcon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_portcon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_genfscon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_genfscon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ipp", "netmask", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon_netmask_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "nnetmask", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_netifcon(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_netifcon_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pirqcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pirqcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_iomemcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_iomemcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_ioportcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_ioportcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pcidevicecon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pcidevicecon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_fsuse(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_fsuse_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sidcontext_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sidcontext", "test", "(", "", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_blockinherit(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "foo", ")", ")", "(", "block", "bar", "(", "type", "a", ")", "(", "blockinherit", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_BLKIN, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_classcommon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "common", "file", "(", "write", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_classcommon_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rolebounds(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_rolebounds_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_callstack(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_call; cil_tree_node_init(&test_ast_node_call); test_ast_node_call->flavor = CIL_CALL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_call; cil_tree_node_init(&test_ast_node_call); test_ast_node_call->flavor = CIL_CALL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); // set optional to disabled ((struct cil_symtab_datum *)test_db->ast->root->cl_head->data)->state = CIL_STATE_DISABLED; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optstack(CuTest *tc) { char *line[] = {"(", "class", "baz", "(", "read", ")", ")", "(", "type", "foo", ")", "(", "type", "bar", ")", "(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optstack_tunable_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_optstack_macro_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodenull_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(NULL, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, NULL); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_dbflavor_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_pass_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_optfailedtoresolve(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_optional *opt; cil_optional_init(&opt); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; test_ast_node_opt->data = opt; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } libsepol/cil/test/unit/test_cil_resolve_ast.h0100644 0000000 0000000 00000064047 13756670065 020542 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_RESOLVE_AST_H_ #define TEST_CIL_RESOLVE_AST_H_ #include "CuTest.h" void test_cil_resolve_name(CuTest *); void test_cil_resolve_name_invalid_type_neg(CuTest *); void test_cil_resolve_ast_curr_null_neg(CuTest *); /* cil_resolve test cases */ void test_cil_resolve_roleallow(CuTest *); void test_cil_resolve_roleallow_srcdecl_neg(CuTest *); void test_cil_resolve_roleallow_tgtdecl_neg(CuTest *); void test_cil_resolve_rolebounds(CuTest *tc); void test_cil_resolve_rolebounds_exists_neg(CuTest *tc); void test_cil_resolve_rolebounds_role1_neg(CuTest *tc); void test_cil_resolve_rolebounds_role2_neg(CuTest *tc); void test_cil_resolve_sensalias(CuTest *); void test_cil_resolve_sensalias_sensdecl_neg(CuTest *); void test_cil_resolve_catalias(CuTest *); void test_cil_resolve_catalias_catdecl_neg(CuTest *); void test_cil_resolve_catorder(CuTest *); void test_cil_resolve_catorder_neg(CuTest *); void test_cil_resolve_dominance(CuTest *); void test_cil_resolve_dominance_neg(CuTest *); void test_cil_resolve_cat_list(CuTest *); void test_cil_resolve_cat_list_catlistnull_neg(CuTest *); void test_cil_resolve_cat_list_rescatlistnull_neg(CuTest *); void test_cil_resolve_cat_list_catrange(CuTest *); void test_cil_resolve_cat_list_catrange_neg(CuTest *); void test_cil_resolve_cat_list_catname_neg(CuTest *); void test_cil_resolve_catset(CuTest *); void test_cil_resolve_catset_catlist_neg(CuTest *); void test_cil_resolve_catrange(CuTest *); void test_cil_resolve_catrange_catloworder_neg(CuTest *); void test_cil_resolve_catrange_cathighorder_neg(CuTest *); void test_cil_resolve_catrange_cat1_neg(CuTest *); void test_cil_resolve_catrange_cat2_neg(CuTest *); void test_cil_resolve_senscat(CuTest *); void test_cil_resolve_senscat_catrange_neg(CuTest *); void test_cil_resolve_senscat_catsetname(CuTest *); void test_cil_resolve_senscat_catsetname_neg(CuTest *); void test_cil_resolve_senscat_sublist(CuTest *); void test_cil_resolve_senscat_missingsens_neg(CuTest *); void test_cil_resolve_senscat_sublist_neg(CuTest *); void test_cil_resolve_senscat_category_neg(CuTest *); void test_cil_resolve_senscat_currrangecat(CuTest *); void test_cil_resolve_senscat_currrangecat_neg(CuTest *); void test_cil_resolve_level(CuTest *); void test_cil_resolve_level_catlist(CuTest *); void test_cil_resolve_level_catset(CuTest *); void test_cil_resolve_level_catset_name_neg(CuTest *); void test_cil_resolve_level_sens_neg(CuTest *); void test_cil_resolve_level_cat_neg(CuTest *); void test_cil_resolve_level_senscat_neg(CuTest *); void test_cil_resolve_levelrange_namedlvl(CuTest *); void test_cil_resolve_levelrange_namedlvl_low_neg(CuTest *); void test_cil_resolve_levelrange_namedlvl_high_neg(CuTest *); void test_cil_resolve_levelrange_anonlvl(CuTest *); void test_cil_resolve_levelrange_anonlvl_low_neg(CuTest *); void test_cil_resolve_levelrange_anonlvl_high_neg(CuTest *); void test_cil_resolve_constrain(CuTest *); void test_cil_resolve_constrain_class_neg(CuTest *); void test_cil_resolve_constrain_perm_neg(CuTest *); void test_cil_resolve_constrain_perm_resolve_neg(CuTest *); void test_cil_resolve_context(CuTest *); void test_cil_resolve_context_macro(CuTest *); void test_cil_resolve_context_macro_neg(CuTest *); void test_cil_resolve_context_namedrange(CuTest *); void test_cil_resolve_context_namedrange_neg(CuTest *); void test_cil_resolve_context_macro_namedrange_anon(CuTest *); void test_cil_resolve_context_user_neg(CuTest *); void test_cil_resolve_context_role_neg(CuTest *); void test_cil_resolve_context_type_neg(CuTest *); void test_cil_resolve_context_anon_level_neg(CuTest *); void test_cil_resolve_roletransition(CuTest *); void test_cil_resolve_roletransition_srcdecl_neg(CuTest *); void test_cil_resolve_roletransition_tgtdecl_neg(CuTest *); void test_cil_resolve_roletransition_resultdecl_neg(CuTest *); void test_cil_resolve_typeattributeset_type_in_multiple_attrs(CuTest *); void test_cil_resolve_typeattributeset_multiple_excludes_with_not(CuTest *); void test_cil_resolve_typeattributeset_multiple_types_with_and(CuTest *); void test_cil_resolve_typeattributeset_using_attr(CuTest *); void test_cil_resolve_typeattributeset_name_neg(CuTest *); void test_cil_resolve_typeattributeset_undef_type_neg(CuTest *); void test_cil_resolve_typeattributeset_not(CuTest *); void test_cil_resolve_typeattributeset_undef_type_not_neg(CuTest *); void test_cil_resolve_typealias(CuTest *); void test_cil_resolve_typealias_neg(CuTest *); void test_cil_resolve_typebounds(CuTest *); void test_cil_resolve_typebounds_repeatbind_neg(CuTest *); void test_cil_resolve_typebounds_type1_neg(CuTest *); void test_cil_resolve_typebounds_type2_neg(CuTest *); void test_cil_resolve_typepermissive(CuTest *); void test_cil_resolve_typepermissive_neg(CuTest *); void test_cil_resolve_nametypetransition(CuTest *); void test_cil_resolve_nametypetransition_src_neg(CuTest *); void test_cil_resolve_nametypetransition_tgt_neg(CuTest *); void test_cil_resolve_nametypetransition_class_neg(CuTest *); void test_cil_resolve_nametypetransition_dest_neg(CuTest *); void test_cil_resolve_rangetransition(CuTest *); void test_cil_resolve_rangetransition_namedrange(CuTest *); void test_cil_resolve_rangetransition_namedrange_anon(CuTest *); void test_cil_resolve_rangetransition_namedrange_anon_neg(CuTest *); void test_cil_resolve_rangetransition_namedrange_neg(CuTest *); void test_cil_resolve_rangetransition_type1_neg(CuTest *); void test_cil_resolve_rangetransition_type2_neg(CuTest *); void test_cil_resolve_rangetransition_class_neg(CuTest *); void test_cil_resolve_rangetransition_call_level_l_anon(CuTest *); void test_cil_resolve_rangetransition_call_level_l_anon_neg(CuTest *); void test_cil_resolve_rangetransition_call_level_h_anon(CuTest *); void test_cil_resolve_rangetransition_call_level_h_anon_neg(CuTest *); void test_cil_resolve_rangetransition_level_l_neg(CuTest *); void test_cil_resolve_rangetransition_level_h_neg(CuTest *); void test_cil_resolve_rangetransition_anon_level_l(CuTest *); void test_cil_resolve_rangetransition_anon_level_l_neg(CuTest *); void test_cil_resolve_rangetransition_anon_level_h(CuTest *); void test_cil_resolve_rangetransition_anon_level_h_neg(CuTest *); void test_cil_resolve_classcommon(CuTest *); void test_cil_resolve_classcommon_no_class_neg(CuTest *); void test_cil_resolve_classcommon_neg(CuTest *); void test_cil_resolve_classcommon_no_common_neg(CuTest *); void test_cil_resolve_classmapping_named(CuTest *); void test_cil_resolve_classmapping_anon(CuTest *); void test_cil_resolve_classmapping_anon_inmacro(CuTest *); void test_cil_resolve_classmapping_anon_inmacro_neg(CuTest *); void test_cil_resolve_classmapping_named_classmapname_neg(CuTest *); void test_cil_resolve_classmapping_anon_classmapname_neg(CuTest *); void test_cil_resolve_classmapping_anon_permset_neg(CuTest *); void test_cil_resolve_classpermset_named(CuTest *); void test_cil_resolve_classpermset_named_namedpermlist(CuTest *); void test_cil_resolve_classpermset_named_permlist_neg(CuTest *); void test_cil_resolve_classpermset_named_unnamedcps_neg(CuTest *); void test_cil_resolve_classpermset_anon(CuTest *); void test_cil_resolve_classpermset_anon_namedpermlist(CuTest *); void test_cil_resolve_classpermset_anon_permlist_neg(CuTest *); void test_cil_resolve_avrule(CuTest *); void test_cil_resolve_avrule_permset(CuTest *); void test_cil_resolve_avrule_permset_neg(CuTest *); void test_cil_resolve_avrule_permset_permdne_neg(CuTest *); void test_cil_resolve_avrule_firsttype_neg(CuTest *); void test_cil_resolve_avrule_secondtype_neg(CuTest *); void test_cil_resolve_avrule_class_neg(CuTest *); void test_cil_resolve_avrule_perm_neg(CuTest *); void test_cil_resolve_type_rule_transition(CuTest *); void test_cil_resolve_type_rule_transition_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_resultdecl_neg(CuTest *); void test_cil_resolve_type_rule_change(CuTest *); void test_cil_resolve_type_rule_change_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_resultdecl_neg(CuTest *); void test_cil_resolve_type_rule_member(CuTest *); void test_cil_resolve_type_rule_member_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_resultdecl_neg(CuTest *); void test_cil_resolve_filecon(CuTest *); void test_cil_resolve_filecon_neg(CuTest *); void test_cil_resolve_filecon_anon_context(CuTest *); void test_cil_resolve_filecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_filecon(CuTest *tc); void test_cil_resolve_ast_node_helper_filecon_neg(CuTest *tc); void test_cil_resolve_portcon(CuTest *); void test_cil_resolve_portcon_neg(CuTest *); void test_cil_resolve_portcon_anon_context(CuTest *); void test_cil_resolve_portcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_portcon(CuTest *tc); void test_cil_resolve_ast_node_helper_portcon_neg(CuTest *tc); void test_cil_resolve_genfscon(CuTest *); void test_cil_resolve_genfscon_neg(CuTest *); void test_cil_resolve_genfscon_anon_context(CuTest *); void test_cil_resolve_genfscon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_genfscon(CuTest *tc); void test_cil_resolve_ast_node_helper_genfscon_neg(CuTest *tc); void test_cil_resolve_nodecon_ipv4(CuTest *); void test_cil_resolve_nodecon_ipv6(CuTest *); void test_cil_resolve_nodecon_anonipaddr_ipv4(CuTest *); void test_cil_resolve_nodecon_anonnetmask_ipv4(CuTest *); void test_cil_resolve_nodecon_anonipaddr_ipv6(CuTest *); void test_cil_resolve_nodecon_anonnetmask_ipv6(CuTest *); void test_cil_resolve_nodecon_diffipfam_neg(CuTest *); void test_cil_resolve_nodecon_context_neg(CuTest *); void test_cil_resolve_nodecon_ipaddr_neg(CuTest *); void test_cil_resolve_nodecon_netmask_neg(CuTest *); void test_cil_resolve_nodecon_anon_context(CuTest *); void test_cil_resolve_nodecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_nodecon(CuTest *tc); void test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_nodecon_netmask_neg(CuTest *tc); void test_cil_resolve_netifcon(CuTest *); void test_cil_resolve_netifcon_otf_neg(CuTest *); void test_cil_resolve_netifcon_interface_neg(CuTest *); void test_cil_resolve_netifcon_unnamed(CuTest *); void test_cil_resolve_netifcon_unnamed_packet_neg(CuTest *); void test_cil_resolve_netifcon_unnamed_otf_neg(CuTest *); void test_cil_resolve_ast_node_helper_netifcon(CuTest *tc); void test_cil_resolve_ast_node_helper_netifcon_neg(CuTest *tc); void test_cil_resolve_pirqcon(CuTest *); void test_cil_resolve_pirqcon_context_neg(CuTest *); void test_cil_resolve_pirqcon_anon_context(CuTest *); void test_cil_resolve_pirqcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_pirqcon(CuTest *tc); void test_cil_resolve_ast_node_helper_pirqcon_neg(CuTest *tc); void test_cil_resolve_iomemcon(CuTest *); void test_cil_resolve_iomemcon_context_neg(CuTest *); void test_cil_resolve_iomemcon_anon_context(CuTest *); void test_cil_resolve_iomemcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_iomemcon(CuTest *tc); void test_cil_resolve_ast_node_helper_iomemcon_neg(CuTest *tc); void test_cil_resolve_ioportcon(CuTest *); void test_cil_resolve_ioportcon_context_neg(CuTest *); void test_cil_resolve_ioportcon_anon_context(CuTest *); void test_cil_resolve_ioportcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_ioportcon(CuTest *tc); void test_cil_resolve_ast_node_helper_ioportcon_neg(CuTest *tc); void test_cil_resolve_pcidevicecon(CuTest *); void test_cil_resolve_pcidevicecon_context_neg(CuTest *); void test_cil_resolve_pcidevicecon_anon_context(CuTest *); void test_cil_resolve_pcidevicecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_pcidevicecon(CuTest *tc); void test_cil_resolve_ast_node_helper_pcidevicecon_neg(CuTest *tc); void test_cil_resolve_fsuse(CuTest *); void test_cil_resolve_fsuse_neg(CuTest *); void test_cil_resolve_fsuse_anon(CuTest *); void test_cil_resolve_fsuse_anon_neg(CuTest *); void test_cil_resolve_ast_node_helper_fsuse(CuTest *tc); void test_cil_resolve_ast_node_helper_fsuse_neg(CuTest *tc); void test_cil_resolve_sidcontext(CuTest *); void test_cil_resolve_sidcontext_named_levels(CuTest *); void test_cil_resolve_sidcontext_named_context(CuTest *); void test_cil_resolve_sidcontext_named_context_wrongname_neg(CuTest *tc); void test_cil_resolve_sidcontext_named_context_invaliduser_neg(CuTest *tc); void test_cil_resolve_sidcontext_named_context_sidcontextnull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_sidcontext(CuTest *tc); void test_cil_resolve_ast_node_helper_sidcontext_neg(CuTest *tc); void test_cil_resolve_blockinherit(CuTest *); void test_cil_resolve_blockinherit_blockstrdne_neg(CuTest *); void test_cil_resolve_ast_node_helper_blockinherit(CuTest *tc); void test_cil_resolve_in_block(CuTest *); void test_cil_resolve_in_blockstrdne_neg(CuTest *); void test_cil_resolve_in_macro(CuTest *); void test_cil_resolve_in_optional(CuTest *); void test_cil_resolve_call1_noparam(CuTest *); void test_cil_resolve_call1_type(CuTest *); void test_cil_resolve_call1_role(CuTest *); void test_cil_resolve_call1_user(CuTest *); void test_cil_resolve_call1_sens(CuTest *); void test_cil_resolve_call1_cat(CuTest *); void test_cil_resolve_call1_catset(CuTest *); void test_cil_resolve_call1_catset_anon(CuTest *); void test_cil_resolve_call1_catset_anon_neg(CuTest *); void test_cil_resolve_call1_level(CuTest *); void test_cil_resolve_call1_class(CuTest *); void test_cil_resolve_call1_classmap(CuTest *); void test_cil_resolve_call1_permset(CuTest *); void test_cil_resolve_call1_permset_anon(CuTest *); void test_cil_resolve_call1_classpermset_named(CuTest *); void test_cil_resolve_call1_classpermset_anon(CuTest *); void test_cil_resolve_call1_classpermset_anon_neg(CuTest *); void test_cil_resolve_call1_level(CuTest *); void test_cil_resolve_call1_level_anon(CuTest *); void test_cil_resolve_call1_level_anon_neg(CuTest *); void test_cil_resolve_call1_ipaddr(CuTest *); void test_cil_resolve_call1_ipaddr_anon(CuTest *); void test_cil_resolve_call1_ipaddr_anon_neg(CuTest *); void test_cil_resolve_call1_unknown_neg(CuTest *); void test_cil_resolve_call1_unknowncall_neg(CuTest *); void test_cil_resolve_call1_extraargs_neg(CuTest *); void test_cil_resolve_call1_copy_dup(CuTest *); void test_cil_resolve_call1_missing_arg_neg(CuTest *); void test_cil_resolve_call1_paramsflavor_neg(CuTest *); void test_cil_resolve_call1_unknownflavor_neg(CuTest *); void test_cil_resolve_call2_type(CuTest *); void test_cil_resolve_call2_role(CuTest *); void test_cil_resolve_call2_user(CuTest *); void test_cil_resolve_call2_sens(CuTest *); void test_cil_resolve_call2_cat(CuTest *); void test_cil_resolve_call2_catset(CuTest *); void test_cil_resolve_call2_catset_anon(CuTest *); void test_cil_resolve_call2_permset(CuTest *); void test_cil_resolve_call2_permset_anon(CuTest *); void test_cil_resolve_call2_classpermset_named(CuTest *); void test_cil_resolve_call2_classpermset_anon(CuTest *); void test_cil_resolve_call2_class(CuTest *); void test_cil_resolve_call2_classmap(CuTest *); void test_cil_resolve_call2_level(CuTest *); void test_cil_resolve_call2_level_anon(CuTest *); void test_cil_resolve_call2_ipaddr(CuTest *); void test_cil_resolve_call2_ipaddr_anon(CuTest *); void test_cil_resolve_call2_unknown_neg(CuTest *); void test_cil_resolve_name_call_args(CuTest *); void test_cil_resolve_name_call_args_multipleparams(CuTest *); void test_cil_resolve_name_call_args_diffflavor(CuTest *); void test_cil_resolve_name_call_args_callnull_neg(CuTest *); void test_cil_resolve_name_call_args_namenull_neg(CuTest *); void test_cil_resolve_name_call_args_callargsnull_neg(CuTest *); void test_cil_resolve_name_call_args_name_neg(CuTest *); void test_cil_resolve_expr_stack_bools(CuTest *); void test_cil_resolve_expr_stack_tunables(CuTest *); void test_cil_resolve_expr_stack_type(CuTest *); void test_cil_resolve_expr_stack_role(CuTest *); void test_cil_resolve_expr_stack_user(CuTest *); void test_cil_resolve_expr_stack_neg(CuTest *); void test_cil_resolve_expr_stack_emptystr_neg(CuTest *); void test_cil_resolve_boolif(CuTest *); void test_cil_resolve_boolif_neg(CuTest *); void test_cil_evaluate_expr_stack_and(CuTest *); void test_cil_evaluate_expr_stack_not(CuTest *); void test_cil_evaluate_expr_stack_or(CuTest *); void test_cil_evaluate_expr_stack_xor(CuTest *); void test_cil_evaluate_expr_stack_eq(CuTest *); void test_cil_evaluate_expr_stack_neq(CuTest *); void test_cil_evaluate_expr_stack_oper1(CuTest *); void test_cil_evaluate_expr_stack_oper2(CuTest *); void test_cil_evaluate_expr_stack_neg(CuTest *); void test_cil_resolve_tunif_false(CuTest *); void test_cil_resolve_tunif_true(CuTest *); void test_cil_resolve_tunif_resolveexpr_neg(CuTest *); void test_cil_resolve_tunif_evaluateexpr_neg(CuTest *); void test_cil_resolve_userbounds(CuTest *tc); void test_cil_resolve_userbounds_exists_neg(CuTest *tc); void test_cil_resolve_userbounds_user1_neg(CuTest *tc); void test_cil_resolve_userbounds_user2_neg(CuTest *tc); void test_cil_resolve_roletype(CuTest *tc); void test_cil_resolve_roletype_type_neg(CuTest *tc); void test_cil_resolve_roletype_role_neg(CuTest *tc); void test_cil_resolve_userrole(CuTest *tc); void test_cil_resolve_userrole_user_neg(CuTest *tc); void test_cil_resolve_userrole_role_neg(CuTest *tc); void test_cil_resolve_userlevel(CuTest *tc); void test_cil_resolve_userlevel_macro(CuTest *tc); void test_cil_resolve_userlevel_macro_neg(CuTest *tc); void test_cil_resolve_userlevel_level_anon(CuTest *tc); void test_cil_resolve_userlevel_level_anon_neg(CuTest *tc); void test_cil_resolve_userlevel_user_neg(CuTest *tc); void test_cil_resolve_userlevel_level_neg(CuTest *tc); void test_cil_resolve_userrange(CuTest *tc); void test_cil_resolve_userrange_macro(CuTest *tc); void test_cil_resolve_userrange_macro_neg(CuTest *tc); void test_cil_resolve_userrange_range_anon(CuTest *tc); void test_cil_resolve_userrange_range_anon_neg(CuTest *tc); void test_cil_resolve_userrange_user_neg(CuTest *tc); void test_cil_resolve_userrange_range_neg(CuTest *tc); void test_cil_disable_children_helper_optional_enabled(CuTest *tc); void test_cil_disable_children_helper_optional_disabled(CuTest *tc); void test_cil_disable_children_helper_block(CuTest *tc); void test_cil_disable_children_helper_user(CuTest *tc); void test_cil_disable_children_helper_role(CuTest *tc); void test_cil_disable_children_helper_type(CuTest *tc); void test_cil_disable_children_helper_typealias(CuTest *tc); void test_cil_disable_children_helper_common(CuTest *tc); void test_cil_disable_children_helper_class(CuTest *tc); void test_cil_disable_children_helper_bool(CuTest *tc); void test_cil_disable_children_helper_sens(CuTest *tc); void test_cil_disable_children_helper_cat(CuTest *tc); void test_cil_disable_children_helper_catset(CuTest *tc); void test_cil_disable_children_helper_sid(CuTest *tc); void test_cil_disable_children_helper_macro(CuTest *tc); void test_cil_disable_children_helper_context(CuTest *tc); void test_cil_disable_children_helper_level(CuTest *tc); void test_cil_disable_children_helper_policycap(CuTest *tc); void test_cil_disable_children_helper_perm(CuTest *tc); void test_cil_disable_children_helper_catalias(CuTest *tc); void test_cil_disable_children_helper_sensalias(CuTest *tc); void test_cil_disable_children_helper_tunable(CuTest *tc); void test_cil_disable_children_helper_unknown(CuTest *tc); /* __cil_resolve_ast_node_helper test cases */ void test_cil_resolve_ast_node_helper_call1(CuTest *); void test_cil_resolve_ast_node_helper_call1_neg(CuTest *); void test_cil_resolve_ast_node_helper_call2(CuTest *); void test_cil_resolve_ast_node_helper_call2_neg(CuTest *); void test_cil_resolve_ast_node_helper_boolif(CuTest *); void test_cil_resolve_ast_node_helper_boolif_neg(CuTest *); void test_cil_resolve_ast_node_helper_tunif(CuTest *); void test_cil_resolve_ast_node_helper_tunif_neg(CuTest *); void test_cil_resolve_ast_node_helper_catorder(CuTest *); void test_cil_resolve_ast_node_helper_catorder_neg(CuTest *); void test_cil_resolve_ast_node_helper_dominance(CuTest *); void test_cil_resolve_ast_node_helper_dominance_neg(CuTest *); void test_cil_resolve_ast_node_helper_roleallow(CuTest *); void test_cil_resolve_ast_node_helper_roleallow_neg(CuTest *); void test_cil_resolve_ast_node_helper_rolebounds(CuTest *tc); void test_cil_resolve_ast_node_helper_rolebounds_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_sensalias(CuTest *); void test_cil_resolve_ast_node_helper_sensalias_neg(CuTest *); void test_cil_resolve_ast_node_helper_catalias(CuTest *); void test_cil_resolve_ast_node_helper_catalias_neg(CuTest *); void test_cil_resolve_ast_node_helper_catset(CuTest *); void test_cil_resolve_ast_node_helper_catset_catlist_neg(CuTest *); void test_cil_resolve_ast_node_helper_level(CuTest *); void test_cil_resolve_ast_node_helper_level_neg(CuTest *); void test_cil_resolve_ast_node_helper_levelrange(CuTest *); void test_cil_resolve_ast_node_helper_levelrange_neg(CuTest *); void test_cil_resolve_ast_node_helper_constrain(CuTest *); void test_cil_resolve_ast_node_helper_constrain_neg(CuTest *); void test_cil_resolve_ast_node_helper_mlsconstrain(CuTest *); void test_cil_resolve_ast_node_helper_mlsconstrain_neg(CuTest *); void test_cil_resolve_ast_node_helper_context(CuTest *); void test_cil_resolve_ast_node_helper_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_catrange(CuTest *tc); void test_cil_resolve_ast_node_helper_catrange_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_senscat(CuTest *tc); void test_cil_resolve_ast_node_helper_senscat_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletransition(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_typeattributeset(CuTest *); void test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg(CuTest *); void test_cil_resolve_ast_node_helper_typealias(CuTest *); void test_cil_resolve_ast_node_helper_typealias_notype_neg(CuTest *); void test_cil_resolve_ast_node_helper_typebounds(CuTest *); void test_cil_resolve_ast_node_helper_typebounds_neg(CuTest *); void test_cil_resolve_ast_node_helper_typepermissive(CuTest *); void test_cil_resolve_ast_node_helper_typepermissive_neg(CuTest *); void test_cil_resolve_ast_node_helper_nametypetransition(CuTest *); void test_cil_resolve_ast_node_helper_nametypetransition_neg(CuTest *); void test_cil_resolve_ast_node_helper_rangetransition(CuTest *); void test_cil_resolve_ast_node_helper_rangetransition_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule(CuTest *); void test_cil_resolve_ast_node_helper_avrule_src_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_class_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_datum_null_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_transition(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_transition_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_change(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_change_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_member(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_member_neg(CuTest *); void test_cil_resolve_ast_node_helper_userbounds(CuTest *tc); void test_cil_resolve_ast_node_helper_userbounds_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype_role_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype_type_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole_user_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole_role_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrange(CuTest *tc); void test_cil_resolve_ast_node_helper_userrange_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_classcommon(CuTest *tc); void test_cil_resolve_ast_node_helper_classcommon_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_callstack(CuTest *tc); void test_cil_resolve_ast_node_helper_call(CuTest *tc); void test_cil_resolve_ast_node_helper_optional(CuTest *tc); void test_cil_resolve_ast_node_helper_macro(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack_tunable_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack_macro_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_nodenull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_extraargsnull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_optfailedtoresolve(CuTest *tc); #endif libsepol/cil/test/unit/test_cil_symtab.c0100644 0000000 0000000 00000004727 13756670065 017505 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_symtab.h" #include "../../src/cil_tree.h" #include "../../src/cil_symtab.h" #include "../../src/cil_internal.h" void test_cil_symtab_insert(CuTest *tc) { symtab_t *test_symtab = NULL; char* test_name = "test"; struct cil_block *test_block = malloc(sizeof(*test_block)); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_array_init(test_block->symtab, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK]); test_block->is_abstract = 0; cil_get_symtab(test_db, test_ast_node->parent, &test_symtab, CIL_SYM_BLOCKS); int rc = cil_symtab_insert(test_symtab, (hashtab_key_t)test_name, (struct cil_symtab_datum*)test_block, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } libsepol/cil/test/unit/test_cil_symtab.h0100644 0000000 0000000 00000003307 13756670065 017503 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_SYMTAB_H_ #define TEST_CIL_SYMTAB_H_ #include "CuTest.h" void test_cil_symtab_insert(CuTest *); #endif libsepol/cil/test/unit/test_cil_tree.c0100644 0000000 0000000 00000005421 13756670065 017135 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_tree.h" #include "../../src/cil_tree.h" void test_cil_tree_node_init(CuTest *tc) { struct cil_tree_node *test_node; cil_tree_node_init(&test_node); CuAssertPtrNotNull(tc, test_node); CuAssertPtrEquals(tc, NULL, test_node->cl_head); CuAssertPtrEquals(tc, NULL, test_node->cl_tail); CuAssertPtrEquals(tc, NULL, test_node->parent); CuAssertPtrEquals(tc, NULL, test_node->data); CuAssertPtrEquals(tc, NULL, test_node->next); CuAssertIntEquals(tc, 0, test_node->flavor); CuAssertIntEquals(tc, 0, test_node->line); free(test_node); } void test_cil_tree_init(CuTest *tc) { struct cil_tree *test_tree; int rc = cil_tree_init(&test_tree); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_tree); CuAssertPtrEquals(tc, NULL, test_tree->root->cl_head); CuAssertPtrEquals(tc, NULL, test_tree->root->cl_tail); CuAssertPtrEquals(tc, NULL, test_tree->root->parent); CuAssertPtrEquals(tc, NULL, test_tree->root->data); CuAssertPtrEquals(tc, NULL, test_tree->root->next); CuAssertIntEquals(tc, 0, test_tree->root->flavor); CuAssertIntEquals(tc, 0, test_tree->root->line); free(test_tree); } libsepol/cil/test/unit/test_cil_tree.h0100644 0000000 0000000 00000003347 13756670065 017147 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_TREE_H_ #define TEST_CIL_TREE_H_ #include "CuTest.h" void test_cil_tree_node_init(CuTest *); void test_cil_tree_init(CuTest *); #endif libsepol/cil/test/unit/test_integration.c0100644 0000000 0000000 00000006173 13756670065 017677 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_integration.h" #include #include #include #include #include void test_integration(CuTest *tc) { int status = 0, status1 = 0, status2 = 0; status = system("./secilc -M -c 24 test/integration.cil &> /dev/null"); if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGQUIT)) printf("Call to system for secilc failed.\n"); status1 = system("checkpolicy -M -c 24 -o policy.conf.24 test/policy.conf &> /dev/null"); if (WIFSIGNALED(status1) && (WTERMSIG(status1) == SIGINT || WTERMSIG(status1) == SIGQUIT)) printf("Call to checkpolicy failed.\n"); status2 = system("sediff -q policy.24 \\; policy.conf.24 &> /dev/null"); if (WIFSIGNALED(status2) && (WTERMSIG(status2) == SIGINT || WTERMSIG(status2) == SIGQUIT)) printf("Call to sediff for secilc failed.\n"); CuAssertIntEquals(tc, 1, WIFEXITED(status)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status)); CuAssertIntEquals(tc, 1, WIFEXITED(status1)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status1)); CuAssertIntEquals(tc, 1, WIFEXITED(status2)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status2)); } void test_min_policy(CuTest *tc) { int status = 0; status = system("./secilc -M -c 24 test/policy.cil &> /dev/null"); if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGQUIT)) printf("Call to system for secilc failed.\n"); CuAssertIntEquals(tc, 1, WIFEXITED(status)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status)); } libsepol/cil/test/unit/test_integration.h0100644 0000000 0000000 00000003341 13756670065 017676 0ustar000000000 0000000 /* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_INTEGRATION_H #define TEST_INTEGRATION_H #include "CuTest.h" void test_min_policy(CuTest *); void test_integration(CuTest *); #endif libsepol/include/0040755 0000000 0000000 00000000000 13756670065 013063 5ustar000000000 0000000 libsepol/include/Makefile0100644 0000000 0000000 00000001147 13756670065 014523 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr INCDIR = $(PREFIX)/include/sepol CILDIR ?= ../cil all: install: all test -d $(DESTDIR)$(INCDIR) || install -m 755 -d $(DESTDIR)$(INCDIR) test -d $(DESTDIR)$(INCDIR)/policydb || install -m 755 -d $(DESTDIR)$(INCDIR)/policydb test -d $(DESTDIR)$(INCDIR)/cil || install -m 755 -d $(DESTDIR)$(INCDIR)/cil install -m 644 $(wildcard sepol/*.h) $(DESTDIR)$(INCDIR) install -m 644 $(wildcard sepol/policydb/*.h) $(DESTDIR)$(INCDIR)/policydb install -m 644 $(wildcard $(CILDIR)/include/cil/*.h) $(DESTDIR)$(INCDIR)/cil indent: ../../scripts/Lindent $(wildcard sepol/*.h) libsepol/include/sepol/0040755 0000000 0000000 00000000000 13756670065 014205 5ustar000000000 0000000 libsepol/include/sepol/boolean_record.h0100644 0000000 0000000 00000003017 13756670065 017331 0ustar000000000 0000000 #ifndef _SEPOL_BOOLEAN_RECORD_H_ #define _SEPOL_BOOLEAN_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_bool; struct sepol_bool_key; typedef struct sepol_bool sepol_bool_t; typedef struct sepol_bool_key sepol_bool_key_t; /* Key */ extern int sepol_bool_key_create(sepol_handle_t * handle, const char *name, sepol_bool_key_t ** key); extern void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name); extern int sepol_bool_key_extract(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_key_t ** key_ptr); extern void sepol_bool_key_free(sepol_bool_key_t * key); extern int sepol_bool_compare(const sepol_bool_t * boolean, const sepol_bool_key_t * key); extern int sepol_bool_compare2(const sepol_bool_t * boolean, const sepol_bool_t * boolean2); /* Name */ extern const char *sepol_bool_get_name(const sepol_bool_t * boolean); extern int sepol_bool_set_name(sepol_handle_t * handle, sepol_bool_t * boolean, const char *name); /* Value */ extern int sepol_bool_get_value(const sepol_bool_t * boolean); extern void sepol_bool_set_value(sepol_bool_t * boolean, int value); /* Create/Clone/Destroy */ extern int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr); extern int sepol_bool_clone(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_t ** bool_ptr); extern void sepol_bool_free(sepol_bool_t * boolean); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/booleans.h0100644 0000000 0000000 00000004304 13756670065 016156 0ustar000000000 0000000 #ifndef _SEPOL_BOOLEANS_H_ #define _SEPOL_BOOLEANS_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /*--------------compatibility--------------*/ /* Given an existing binary policy (starting at 'data', with length 'len') and a boolean configuration file named by 'boolpath', rewrite the binary policy for the boolean settings in the boolean configuration file. The binary policy is rewritten in place in memory. Returns 0 upon success, or -1 otherwise. */ extern int sepol_genbools(void *data, size_t len, const char *boolpath); /* Given an existing binary policy (starting at 'data', with length 'len') and boolean settings specified by the parallel arrays ('names', 'values') with 'nel' elements, rewrite the binary policy for the boolean settings. The binary policy is rewritten in place in memory. Returns 0 upon success or -1 otherwise. */ extern int sepol_genbools_array(void *data, size_t len, char **names, int *values, int nel); /*---------------end compatbility------------*/ /* Set the specified boolean */ extern int sepol_bool_set(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_bool_key_t * key, const sepol_bool_t * data); /* Return the number of booleans */ extern int sepol_bool_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if the specified boolean exists */ extern int sepol_bool_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_bool_key_t * key, int *response); /* Query a boolean - returns the boolean, or NULL if not found */ extern int sepol_bool_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, sepol_bool_t ** response); /* Iterate the booleans * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_bool_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_bool_t * boolean, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/context.h0100644 0000000 0000000 00000001360 13756670065 016037 0ustar000000000 0000000 #ifndef _SEPOL_CONTEXT_H_ #define _SEPOL_CONTEXT_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* -- Deprecated -- */ extern int sepol_check_context(const char *context); /* -- End deprecated -- */ extern int sepol_context_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_context_t * context); extern int sepol_mls_contains(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls1, const char *mls2, int *response); extern int sepol_mls_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/context_record.h0100644 0000000 0000000 00000003206 13756670065 017376 0ustar000000000 0000000 #ifndef _SEPOL_CONTEXT_RECORD_H_ #define _SEPOL_CONTEXT_RECORD_H_ #include #ifdef __cplusplus extern "C" { #endif struct sepol_context; typedef struct sepol_context sepol_context_t; /* We don't need a key, because the context is never stored * in a data collection by itself */ /* User */ extern const char *sepol_context_get_user(const sepol_context_t * con); extern int sepol_context_set_user(sepol_handle_t * handle, sepol_context_t * con, const char *user); /* Role */ extern const char *sepol_context_get_role(const sepol_context_t * con); extern int sepol_context_set_role(sepol_handle_t * handle, sepol_context_t * con, const char *role); /* Type */ extern const char *sepol_context_get_type(const sepol_context_t * con); extern int sepol_context_set_type(sepol_handle_t * handle, sepol_context_t * con, const char *type); /* MLS */ extern const char *sepol_context_get_mls(const sepol_context_t * con); extern int sepol_context_set_mls(sepol_handle_t * handle, sepol_context_t * con, const char *mls_range); /* Create/Clone/Destroy */ extern int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr); extern int sepol_context_clone(sepol_handle_t * handle, const sepol_context_t * con, sepol_context_t ** con_ptr); extern void sepol_context_free(sepol_context_t * con); /* Parse to/from string */ extern int sepol_context_from_string(sepol_handle_t * handle, const char *str, sepol_context_t ** con); extern int sepol_context_to_string(sepol_handle_t * handle, const sepol_context_t * con, char **str_ptr); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/debug.h0100644 0000000 0000000 00000001717 13756670065 015447 0ustar000000000 0000000 #ifndef _SEPOL_DEBUG_H_ #define _SEPOL_DEBUG_H_ #include #ifdef __cplusplus extern "C" { #endif /* Deprecated */ extern void sepol_debug(int on); /* End deprecated */ #define SEPOL_MSG_ERR 1 #define SEPOL_MSG_WARN 2 #define SEPOL_MSG_INFO 3 extern int sepol_msg_get_level(sepol_handle_t * handle); extern const char *sepol_msg_get_channel(sepol_handle_t * handle); extern const char *sepol_msg_get_fname(sepol_handle_t * handle); /* Set the messaging callback. * By the default, the callback will print * the message on standard output, in a * particular format. Passing NULL here * indicates that messaging should be suppressed */ extern void sepol_msg_set_callback(sepol_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...), void *msg_callback_arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/errcodes.h0100644 0000000 0000000 00000001523 13756670065 016162 0ustar000000000 0000000 /* Author: Karl MacMillan */ #ifndef __sepol_errno_h__ #define __sepol_errno_h__ #include #ifdef __cplusplus extern "C" { #endif #define SEPOL_OK 0 /* These first error codes are defined for compatibility with * previous version of libsepol. In the future, custom error * codes that don't map to system error codes should be defined * outside of the range of system error codes. */ #define SEPOL_ERR -1 #define SEPOL_ENOTSUP -2 /* feature not supported in module language */ #define SEPOL_EREQ -3 /* requirements not met */ /* Error codes that map to system error codes */ #define SEPOL_ENOMEM -ENOMEM #define SEPOL_ERANGE -ERANGE #define SEPOL_EEXIST -EEXIST #define SEPOL_ENOENT -ENOENT #ifdef __cplusplus } #endif #endif libsepol/include/sepol/handle.h0100644 0000000 0000000 00000002561 13756670065 015612 0ustar000000000 0000000 #ifndef _SEPOL_HANDLE_H_ #define _SEPOL_HANDLE_H_ #ifdef __cplusplus extern "C" { #endif struct sepol_handle; typedef struct sepol_handle sepol_handle_t; /* Create and return a sepol handle. */ sepol_handle_t *sepol_handle_create(void); /* Get whether or not dontaudits will be disabled, same values as * specified by set_disable_dontaudit. This value reflects the state * your system will be set to upon commit, not necessarily its * current state.*/ int sepol_get_disable_dontaudit(sepol_handle_t * sh); /* Set whether or not to disable dontaudits, 0 is default and does * not disable dontaudits, 1 disables them */ void sepol_set_disable_dontaudit(sepol_handle_t * sh, int disable_dontaudit); /* Set whether module_expand() should consume the base policy passed in. * This should reduce the amount of memory required to expand the policy. */ void sepol_set_expand_consume_base(sepol_handle_t * sh, int consume_base); /* Destroy a sepol handle. */ void sepol_handle_destroy(sepol_handle_t *); /* Get whether or not needless unused branch of tunables would be preserved */ int sepol_get_preserve_tunables(sepol_handle_t * sh); /* Set whether or not to preserve the needless unused branch of tunables, * 0 is default and discard such branch, 1 preserves them */ void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/ibendport_record.h0100644 0000000 0000000 00000004206 13756670065 017701 0ustar000000000 0000000 #ifndef _SEPOL_IBENDPORT_RECORD_H_ #define _SEPOL_IBENDPORT_RECORD_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_ibendport; struct sepol_ibendport_key; typedef struct sepol_ibendport sepol_ibendport_t; typedef struct sepol_ibendport_key sepol_ibendport_key_t; extern int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key); extern int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2); extern int sepol_ibendport_key_create(sepol_handle_t *handle, const char *ibdev_name, int port, sepol_ibendport_key_t **key_ptr); extern void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, const char **ibdev_name, int *port); extern int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, char **ibdev_name); extern int sepol_ibendport_key_extract(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_key_t **key_ptr); extern void sepol_ibendport_key_free(sepol_ibendport_key_t *key); extern void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port); extern int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport); extern int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, char **ibdev_name); extern int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, sepol_ibendport_t *ibendport, const char *ibdev_name); extern sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport); extern int sepol_ibendport_set_con(sepol_handle_t *handle, sepol_ibendport_t *ibendport, sepol_context_t *con); extern int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport_ptr); extern int sepol_ibendport_clone(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_t **ibendport_ptr); extern void sepol_ibendport_free(sepol_ibendport_t *ibendport); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/ibendports.h0100644 0000000 0000000 00000002553 13756670065 016531 0ustar000000000 0000000 #ifndef _SEPOL_IBENDPORTS_H_ #define _SEPOL_IBENDPORTS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ibendports */ extern int sepol_ibendport_count(sepol_handle_t *handle, const sepol_policydb_t *p, unsigned int *response); /* Check if a ibendport exists */ extern int sepol_ibendport_exists(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, int *response); /* Query a ibendport - returns the ibendport, or NULL if not found */ extern int sepol_ibendport_query(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, sepol_ibendport_t **response); /* Modify a ibendport, or add it, if the key is not found */ extern int sepol_ibendport_modify(sepol_handle_t *handle, sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, const sepol_ibendport_t *data); /* Iterate the ibendports * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_ibendport_iterate(sepol_handle_t *handle, const sepol_policydb_t *policydb, int (*fn)(const sepol_ibendport_t *ibendport, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/ibpkey_record.h0100644 0000000 0000000 00000004375 13756670065 017205 0ustar000000000 0000000 #ifndef _SEPOL_IBPKEY_RECORD_H_ #define _SEPOL_IBPKEY_RECORD_H_ #include #include #include #include #define INET6_ADDRLEN 16 #ifdef __cplusplus extern "C" { #endif struct sepol_ibpkey; struct sepol_ibpkey_key; typedef struct sepol_ibpkey sepol_ibpkey_t; typedef struct sepol_ibpkey_key sepol_ibpkey_key_t; extern int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key); extern int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2); extern int sepol_ibpkey_key_create(sepol_handle_t *handle, const char *subnet_prefix, int low, int high, sepol_ibpkey_key_t **key_ptr); extern void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, uint64_t *subnet_prefix, int *low, int *high); extern int sepol_ibpkey_key_extract(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_key_t **key_ptr); extern void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key); extern int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey); extern void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num); extern void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high); extern int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, char **subnet_prefix); extern uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, const char *subnet_prefix); extern void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, uint64_t subnet_prefix); extern sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_set_con(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, sepol_context_t *con); extern int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey_ptr); extern int sepol_ibpkey_clone(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr); extern void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/ibpkeys.h0100644 0000000 0000000 00000002503 13756670065 016021 0ustar000000000 0000000 #ifndef _SEPOL_IBPKEYS_H_ #define _SEPOL_IBPKEYS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ibpkeys */ extern int sepol_ibpkey_count(sepol_handle_t *handle, const sepol_policydb_t *p, unsigned int *response); /* Check if a ibpkey exists */ extern int sepol_ibpkey_exists(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, int *response); /* Query a ibpkey - returns the ibpkey, or NULL if not found */ extern int sepol_ibpkey_query(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response); /* Modify a ibpkey, or add it, if the key is not found */ extern int sepol_ibpkey_modify(sepol_handle_t *handle, sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data); /* Iterate the ibpkeys * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_ibpkey_iterate(sepol_handle_t *handle, const sepol_policydb_t *policydb, int (*fn)(const sepol_ibpkey_t *ibpkey, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/iface_record.h0100644 0000000 0000000 00000003460 13756670065 016763 0ustar000000000 0000000 #ifndef _SEPOL_IFACE_RECORD_H_ #define _SEPOL_IFACE_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_iface; struct sepol_iface_key; typedef struct sepol_iface sepol_iface_t; typedef struct sepol_iface_key sepol_iface_key_t; /* Key */ extern int sepol_iface_compare(const sepol_iface_t * iface, const sepol_iface_key_t * key); extern int sepol_iface_compare2(const sepol_iface_t * iface, const sepol_iface_t * iface2); extern void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name); extern int sepol_iface_key_create(sepol_handle_t * handle, const char *name, sepol_iface_key_t ** key_ptr); extern int sepol_iface_key_extract(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_key_t ** key_ptr); extern void sepol_iface_key_free(sepol_iface_key_t * key); /* Name */ extern const char *sepol_iface_get_name(const sepol_iface_t * iface); extern int sepol_iface_set_name(sepol_handle_t * handle, sepol_iface_t * iface, const char *name); /* Context */ extern sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface); extern int sepol_iface_set_ifcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con); extern sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface); extern int sepol_iface_set_msgcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_iface_create(sepol_handle_t * handle, sepol_iface_t ** iface_ptr); extern int sepol_iface_clone(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_t ** iface_ptr); extern void sepol_iface_free(sepol_iface_t * iface); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/interfaces.h0100644 0000000 0000000 00000002573 13756670065 016505 0ustar000000000 0000000 #ifndef __SEPOL_INTERFACES_H_ #define __SEPOL_INTERFACES_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of interfaces */ extern int sepol_iface_count(sepol_handle_t * handle, const sepol_policydb_t * policydb, unsigned int *response); /* Check if an interface exists */ extern int sepol_iface_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_iface_key_t * key, int *response); /* Query an interface - returns the interface, * or NULL if not found */ extern int sepol_iface_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_iface_key_t * key, sepol_iface_t ** response); /* Modify an interface, or add it, if the key * is not found */ extern int sepol_iface_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_iface_key_t * key, const sepol_iface_t * data); /* Iterate the interfaces * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_iface_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_iface_t * iface, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/kernel_to_cil.h0100644 0000000 0000000 00000000175 13756670065 017167 0ustar000000000 0000000 #include #include int sepol_kernel_policydb_to_cil(FILE *fp, struct policydb *pdb); libsepol/include/sepol/kernel_to_conf.h0100644 0000000 0000000 00000000176 13756670065 017346 0ustar000000000 0000000 #include #include int sepol_kernel_policydb_to_conf(FILE *fp, struct policydb *pdb); libsepol/include/sepol/module.h0100644 0000000 0000000 00000005170 13756670065 015643 0ustar000000000 0000000 #ifndef _SEPOL_MODULE_H_ #define _SEPOL_MODULE_H_ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_module_package; typedef struct sepol_module_package sepol_module_package_t; /* Module package public interfaces. */ extern int sepol_module_package_create(sepol_module_package_t ** p); extern void sepol_module_package_free(sepol_module_package_t * p); extern char *sepol_module_package_get_file_contexts(sepol_module_package_t * p); extern size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p); extern int sepol_module_package_set_file_contexts(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_seusers(sepol_module_package_t * p); extern size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p); extern int sepol_module_package_set_seusers(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_user_extra(sepol_module_package_t * p); extern size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p); extern int sepol_module_package_set_user_extra(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p); extern size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p); extern int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, char *data, size_t len); extern sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p); extern int sepol_link_packages(sepol_handle_t * handle, sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules, int verbose); extern int sepol_module_package_read(sepol_module_package_t * mod, struct sepol_policy_file *file, int verbose); extern int sepol_module_package_info(struct sepol_policy_file *file, int *type, char **name, char **version); extern int sepol_module_package_write(sepol_module_package_t * p, struct sepol_policy_file *file); /* Module linking/expanding public interfaces. */ extern int sepol_link_modules(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t ** modules, size_t len, int verbose); extern int sepol_expand_module(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t * out, int verbose, int check); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/module_to_cil.h0100644 0000000 0000000 00000000511 13756670065 017166 0ustar000000000 0000000 #include #include #include int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked); int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg); int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg); libsepol/include/sepol/node_record.h0100644 0000000 0000000 00000005366 13756670065 016650 0ustar000000000 0000000 #ifndef _SEPOL_NODE_RECORD_H_ #define _SEPOL_NODE_RECORD_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_node; struct sepol_node_key; typedef struct sepol_node sepol_node_t; typedef struct sepol_node_key sepol_node_key_t; #define SEPOL_PROTO_IP4 0 #define SEPOL_PROTO_IP6 1 /* Key */ extern int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key); extern int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2); extern int sepol_node_key_create(sepol_handle_t * handle, const char *addr, const char *mask, int proto, sepol_node_key_t ** key_ptr); extern void sepol_node_key_unpack(const sepol_node_key_t * key, const char **addr, const char **mask, int *proto); extern int sepol_node_key_extract(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_key_t ** key_ptr); extern void sepol_node_key_free(sepol_node_key_t * key); /* Address */ extern int sepol_node_get_addr(sepol_handle_t * handle, const sepol_node_t * node, char **addr); extern int sepol_node_get_addr_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **addr, size_t * addr_sz); extern int sepol_node_set_addr(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *addr); extern int sepol_node_set_addr_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *addr, size_t addr_sz); /* Netmask */ extern int sepol_node_get_mask(sepol_handle_t * handle, const sepol_node_t * node, char **mask); extern int sepol_node_get_mask_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **mask, size_t * mask_sz); extern int sepol_node_set_mask(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *mask); extern int sepol_node_set_mask_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *mask, size_t mask_sz); /* Protocol */ extern int sepol_node_get_proto(const sepol_node_t * node); extern void sepol_node_set_proto(sepol_node_t * node, int proto); extern const char *sepol_node_get_proto_str(int proto); /* Context */ extern sepol_context_t *sepol_node_get_con(const sepol_node_t * node); extern int sepol_node_set_con(sepol_handle_t * handle, sepol_node_t * node, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node_ptr); extern int sepol_node_clone(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_t ** node_ptr); extern void sepol_node_free(sepol_node_t * node); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/nodes.h0100644 0000000 0000000 00000002440 13756670065 015463 0ustar000000000 0000000 #ifndef _SEPOL_NODES_H_ #define _SEPOL_NODES_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of nodes */ extern int sepol_node_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if a node exists */ extern int sepol_node_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_node_key_t * key, int *response); /* Query a node - returns the node, or NULL if not found */ extern int sepol_node_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_node_key_t * key, sepol_node_t ** response); /* Modify a node, or add it, if the key is not found */ extern int sepol_node_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_node_key_t * key, const sepol_node_t * data); /* Iterate the nodes * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_node_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_node_t * node, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb.h0100644 0000000 0000000 00000011127 13756670065 016162 0ustar000000000 0000000 #ifndef _SEPOL_POLICYDB_H_ #define _SEPOL_POLICYDB_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_policy_file; typedef struct sepol_policy_file sepol_policy_file_t; struct sepol_policydb; typedef struct sepol_policydb sepol_policydb_t; /* Policy file public interfaces. */ /* Create and free memory associated with a policy file. */ extern int sepol_policy_file_create(sepol_policy_file_t ** pf); extern void sepol_policy_file_free(sepol_policy_file_t * pf); /* * Set the policy file to represent a binary policy memory image. * Subsequent operations using the policy file will read and write * the image located at the specified address with the specified length. * If 'len' is 0, then merely compute the necessary length upon * subsequent policydb write operations in order to determine the * necessary buffer size to allocate. */ extern void sepol_policy_file_set_mem(sepol_policy_file_t * pf, char *data, size_t len); /* * Get the size of the buffer needed to store a policydb write * previously done on this policy file. */ extern int sepol_policy_file_get_len(sepol_policy_file_t * pf, size_t * len); /* * Set the policy file to represent a FILE. * Subsequent operations using the policy file will read and write * to the FILE. */ extern void sepol_policy_file_set_fp(sepol_policy_file_t * pf, FILE * fp); /* * Associate a handle with a policy file, for use in * error reporting from subsequent calls that take the * policy file as an argument. */ extern void sepol_policy_file_set_handle(sepol_policy_file_t * pf, sepol_handle_t * handle); /* Policydb public interfaces. */ /* Create and free memory associated with a policydb. */ extern int sepol_policydb_create(sepol_policydb_t ** p); extern void sepol_policydb_free(sepol_policydb_t * p); /* Legal types of policies that the policydb can represent. */ #define SEPOL_POLICY_KERN 0 #define SEPOL_POLICY_BASE 1 #define SEPOL_POLICY_MOD 2 /* * Range of policy versions for the kernel policy type supported * by this library. */ extern int sepol_policy_kern_vers_min(void); extern int sepol_policy_kern_vers_max(void); /* * Set the policy type as specified, and automatically initialize the * policy version accordingly to the maximum version supported for the * policy type. * Returns -1 if the policy type is not legal. */ extern int sepol_policydb_set_typevers(sepol_policydb_t * p, unsigned int type); /* * Set the policy version to a different value. * Returns -1 if the policy version is not in the supported range for * the (previously set) policy type. */ extern int sepol_policydb_set_vers(sepol_policydb_t * p, unsigned int vers); /* Set how to handle unknown class/perms. */ #define SEPOL_DENY_UNKNOWN 0 #define SEPOL_REJECT_UNKNOWN 2 #define SEPOL_ALLOW_UNKNOWN 4 extern int sepol_policydb_set_handle_unknown(sepol_policydb_t * p, unsigned int handle_unknown); /* Set the target platform */ #define SEPOL_TARGET_SELINUX 0 #define SEPOL_TARGET_XEN 1 extern int sepol_policydb_set_target_platform(sepol_policydb_t * p, int target_platform); /* * Read a policydb from a policy file. * This automatically sets the type and version based on the * image contents. */ extern int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf); /* * Write a policydb to a policy file. * The generated image will be in the binary format corresponding * to the policy version associated with the policydb. */ extern int sepol_policydb_write(sepol_policydb_t * p, sepol_policy_file_t * pf); /* * Extract a policydb from a binary policy memory image. * This is equivalent to sepol_policydb_read with a policy file * set to refer to memory. */ extern int sepol_policydb_from_image(sepol_handle_t * handle, void *data, size_t len, sepol_policydb_t * p); /* * Generate a binary policy memory image from a policydb. * This is equivalent to sepol_policydb_write with a policy file * set to refer to memory, but internally handles computing the * necessary length and allocating an appropriately sized memory * buffer for the caller. */ extern int sepol_policydb_to_image(sepol_handle_t * handle, sepol_policydb_t * p, void **newdata, size_t * newlen); /* * Check whether the policydb has MLS enabled. */ extern int sepol_policydb_mls_enabled(const sepol_policydb_t * p); /* * Check whether the compatibility mode for SELinux network * checks should be enabled when using this policy. */ extern int sepol_policydb_compat_net(const sepol_policydb_t * p); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/0040755 0000000 0000000 00000000000 13756670065 016012 5ustar000000000 0000000 libsepol/include/sepol/policydb/avrule_block.h0100644 0000000 0000000 00000003145 13756670065 020633 0ustar000000000 0000000 /* Authors: Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_AVRULE_BLOCK_H_ #define _SEPOL_AVRULE_BLOCK_H_ #include #ifdef __cplusplus extern "C" { #endif extern avrule_block_t *avrule_block_create(void); extern void avrule_block_destroy(avrule_block_t * x); extern avrule_decl_t *avrule_decl_create(uint32_t decl_id); extern void avrule_decl_destroy(avrule_decl_t * x); extern void avrule_block_list_destroy(avrule_block_t * x); extern avrule_decl_t *get_avrule_decl(policydb_t * p, uint32_t decl_id); extern cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond); extern int is_id_enabled(char *id, policydb_t * p, int symbol_table); extern int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/avtab.h0100644 0000000 0000000 00000011207 13756670065 017256 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura * Tuned number of hash slots for avtab to reduce memory usage */ /* Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Copyright (C) 2003 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * An access vector table (avtab) is a hash table * of access vectors and transition types indexed * by a type pair and a class. An access vector * table is used to represent the type enforcement * tables. */ #ifndef _SEPOL_POLICYDB_AVTAB_H_ #define _SEPOL_POLICYDB_AVTAB_H_ #include #include #ifdef __cplusplus extern "C" { #endif typedef struct avtab_key { uint16_t source_type; uint16_t target_type; uint16_t target_class; #define AVTAB_ALLOWED 0x0001 #define AVTAB_AUDITALLOW 0x0002 #define AVTAB_AUDITDENY 0x0004 #define AVTAB_NEVERALLOW 0x0080 #define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) #define AVTAB_TRANSITION 0x0010 #define AVTAB_MEMBER 0x0020 #define AVTAB_CHANGE 0x0040 #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) #define AVTAB_XPERMS_ALLOWED 0x0100 #define AVTAB_XPERMS_AUDITALLOW 0x0200 #define AVTAB_XPERMS_DONTAUDIT 0x0400 #define AVTAB_XPERMS_NEVERALLOW 0x0800 #define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | AVTAB_XPERMS_DONTAUDIT) #define AVTAB_ENABLED_OLD 0x80000000 #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ uint16_t specified; /* what fields are specified */ } avtab_key_t; typedef struct avtab_extended_perms { #define AVTAB_XPERMS_IOCTLFUNCTION 0x01 #define AVTAB_XPERMS_IOCTLDRIVER 0x02 /* extension of the avtab_key specified */ uint8_t specified; uint8_t driver; uint32_t perms[8]; } avtab_extended_perms_t; typedef struct avtab_datum { uint32_t data; /* access vector or type */ avtab_extended_perms_t *xperms; } avtab_datum_t; typedef struct avtab_node *avtab_ptr_t; struct avtab_node { avtab_key_t key; avtab_datum_t datum; avtab_ptr_t next; void *parse_context; /* generic context pointer used by parser; * not saved in binary policy */ unsigned merged; /* flag for avtab_write only; not saved in binary policy */ }; typedef struct avtab { avtab_ptr_t *htable; uint32_t nel; /* number of elements */ uint32_t nslot; /* number of hash slots */ uint32_t mask; /* mask to compute hash func */ } avtab_t; extern int avtab_init(avtab_t *); extern int avtab_alloc(avtab_t *, uint32_t); extern int avtab_insert(avtab_t * h, avtab_key_t * k, avtab_datum_t * d); extern avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k); extern void avtab_destroy(avtab_t * h); extern int avtab_map(avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args); extern void avtab_hash_eval(avtab_t * h, char *tag); struct policy_file; extern int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, int (*insert) (avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p), void *p); extern int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers); extern avtab_ptr_t avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum); extern avtab_ptr_t avtab_insert_with_parse_context(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum, void *parse_context); extern avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key); extern avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified); #define MAX_AVTAB_HASH_BITS 20 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) /* avtab_alloc uses one bucket per 2-4 elements, so adjust to get maximum buckets */ #define MAX_AVTAB_SIZE (MAX_AVTAB_HASH_BUCKETS << 1) #ifdef __cplusplus } #endif #endif /* _AVTAB_H_ */ /* FLASK */ libsepol/include/sepol/policydb/conditional.h0100644 0000000 0000000 00000011175 13756670065 020470 0ustar000000000 0000000 /* Authors: Karl MacMillan * Frank Mayer * * Copyright (C) 2003 - 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_CONDITIONAL_H_ #define _SEPOL_POLICYDB_CONDITIONAL_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define COND_EXPR_MAXDEPTH 10 /* this is the max unique bools in a conditional expression * for which we precompute all outcomes for the expression. * * NOTE - do _NOT_ use value greater than 5 because * cond_node_t->expr_pre_comp can only hold at most 32 values */ #define COND_MAX_BOOLS 5 /* * A conditional expression is a list of operators and operands * in reverse polish notation. */ typedef struct cond_expr { #define COND_BOOL 1 /* plain bool */ #define COND_NOT 2 /* !bool */ #define COND_OR 3 /* bool || bool */ #define COND_AND 4 /* bool && bool */ #define COND_XOR 5 /* bool ^ bool */ #define COND_EQ 6 /* bool == bool */ #define COND_NEQ 7 /* bool != bool */ #define COND_LAST COND_NEQ uint32_t expr_type; uint32_t bool; struct cond_expr *next; } cond_expr_t; /* * Each cond_node_t contains a list of rules to be enabled/disabled * depending on the current value of the conditional expression. This * struct is for that list. */ typedef struct cond_av_list { avtab_ptr_t node; struct cond_av_list *next; } cond_av_list_t; /* * A cond node represents a conditional block in a policy. It * contains a conditional expression, the current state of the expression, * two lists of rules to enable/disable depending on the value of the * expression (the true list corresponds to if and the false list corresponds * to else).. */ typedef struct cond_node { int cur_state; cond_expr_t *expr; /* these true/false lists point into te_avtab when that is used */ cond_av_list_t *true_list; cond_av_list_t *false_list; /* and these are used during parsing and for modules */ avrule_t *avtrue_list; avrule_t *avfalse_list; /* these fields are not written to binary policy */ unsigned int nbools; uint32_t bool_ids[COND_MAX_BOOLS]; uint32_t expr_pre_comp; struct cond_node *next; /* a tunable conditional, calculated and used at expansion */ #define COND_NODE_FLAGS_TUNABLE 0x01 uint32_t flags; } cond_node_t; extern int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr); extern cond_expr_t *cond_copy_expr(cond_expr_t * expr); extern int cond_expr_equal(cond_node_t * a, cond_node_t * b); extern int cond_normalize_expr(policydb_t * p, cond_node_t * cn); extern void cond_node_destroy(cond_node_t * node); extern void cond_expr_destroy(cond_expr_t * expr); extern cond_node_t *cond_node_find(policydb_t * p, cond_node_t * needle, cond_node_t * haystack, int *was_created); extern cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node); extern cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, cond_node_t * cn); extern int evaluate_conds(policydb_t * p); extern avtab_datum_t *cond_av_list_search(avtab_key_t * key, cond_av_list_t * cond_list); extern void cond_av_list_destroy(cond_av_list_t * list); extern void cond_optimize_lists(cond_list_t * cl); extern int cond_policydb_init(policydb_t * p); extern void cond_policydb_destroy(policydb_t * p); extern void cond_list_destroy(cond_list_t * list); extern int cond_init_bool_indexes(policydb_t * p); extern int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p); extern int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap); extern int cond_read_bool(policydb_t * p, hashtab_t h, struct policy_file *fp); extern int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp); extern void cond_compute_av(avtab_t * ctab, avtab_key_t * key, struct sepol_av_decision *avd); #ifdef __cplusplus } #endif #endif /* _CONDITIONAL_H_ */ libsepol/include/sepol/policydb/constraint.h0100644 0000000 0000000 00000005013 13756670065 020343 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A constraint is a condition that must be satisfied in * order for one or more permissions to be granted. * Constraints are used to impose additional restrictions * beyond the type-based rules in `te' or the role-based * transition rules in `rbac'. Constraints are typically * used to prevent a process from transitioning to a new user * identity or role unless it is in a privileged type. * Constraints are likewise typically used to prevent a * process from labeling an object with a different user * identity. */ #ifndef _SEPOL_POLICYDB_CONSTRAINT_H_ #define _SEPOL_POLICYDB_CONSTRAINT_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif #define CEXPR_MAXDEPTH 5 struct type_set; typedef struct constraint_expr { #define CEXPR_NOT 1 /* not expr */ #define CEXPR_AND 2 /* expr and expr */ #define CEXPR_OR 3 /* expr or expr */ #define CEXPR_ATTR 4 /* attr op attr */ #define CEXPR_NAMES 5 /* attr op names */ uint32_t expr_type; /* expression type */ #define CEXPR_USER 1 /* user */ #define CEXPR_ROLE 2 /* role */ #define CEXPR_TYPE 4 /* type */ #define CEXPR_TARGET 8 /* target if set, source otherwise */ #define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */ #define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */ #define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */ #define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */ #define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */ #define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */ #define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */ uint32_t attr; /* attribute */ #define CEXPR_EQ 1 /* == or eq */ #define CEXPR_NEQ 2 /* != */ #define CEXPR_DOM 3 /* dom */ #define CEXPR_DOMBY 4 /* domby */ #define CEXPR_INCOMP 5 /* incomp */ uint32_t op; /* operator */ ebitmap_t names; /* names */ struct type_set *type_names; struct constraint_expr *next; /* next expression */ } constraint_expr_t; typedef struct constraint_node { sepol_access_vector_t permissions; /* constrained permissions */ constraint_expr_t *expr; /* constraint on permissions */ struct constraint_node *next; /* next constraint */ } constraint_node_t; struct policydb; extern int constraint_expr_init(constraint_expr_t * expr); extern void constraint_expr_destroy(constraint_expr_t * expr); #ifdef __cplusplus } #endif #endif /* _CONSTRAINT_H_ */ /* FLASK */ libsepol/include/sepol/policydb/context.h0100644 0000000 0000000 00000006404 13756670065 017650 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A security context is a set of security attributes * associated with each subject and object controlled * by the security policy. Security contexts are * externally represented as variable-length strings * that can be interpreted by a user or application * with an understanding of the security policy. * Internally, the security server uses a simple * structure. This structure is private to the * security server and can be changed without affecting * clients of the security server. */ #ifndef _SEPOL_POLICYDB_CONTEXT_H_ #define _SEPOL_POLICYDB_CONTEXT_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* * A security context consists of an authenticated user * identity, a role, a type and a MLS range. */ typedef struct context_struct { uint32_t user; uint32_t role; uint32_t type; mls_range_t range; } context_struct_t; static inline void mls_context_init(context_struct_t * c) { mls_range_init(&c->range); } static inline int mls_context_cpy(context_struct_t * dst, context_struct_t * src) { if (mls_range_cpy(&dst->range, &src->range) < 0) return -1; return 0; } /* * Sets both levels in the MLS range of 'dst' to the low level of 'src'. */ static inline int mls_context_cpy_low(context_struct_t *dst, context_struct_t *src) { int rc; dst->range.level[0].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); if (rc) goto out; dst->range.level[1].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat); if (rc) ebitmap_destroy(&dst->range.level[0].cat); out: return rc; } /* * Sets both levels in the MLS range of 'dst' to the high level of 'src'. */ static inline int mls_context_cpy_high(context_struct_t *dst, context_struct_t *src) { int rc; dst->range.level[0].sens = src->range.level[1].sens; rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); if (rc) goto out; dst->range.level[1].sens = src->range.level[1].sens; rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); if (rc) ebitmap_destroy(&dst->range.level[0].cat); out: return rc; } static inline int mls_context_cmp(context_struct_t * c1, context_struct_t * c2) { return (mls_level_eq(&c1->range.level[0], &c2->range.level[0]) && mls_level_eq(&c1->range.level[1], &c2->range.level[1])); } static inline void mls_context_destroy(context_struct_t * c) { if (c == NULL) return; mls_range_destroy(&c->range); mls_context_init(c); } static inline void context_init(context_struct_t * c) { memset(c, 0, sizeof(*c)); } static inline int context_cpy(context_struct_t * dst, context_struct_t * src) { dst->user = src->user; dst->role = src->role; dst->type = src->type; return mls_context_cpy(dst, src); } static inline void context_destroy(context_struct_t * c) { if (c == NULL) return; c->user = c->role = c->type = 0; mls_context_destroy(c); } static inline int context_cmp(context_struct_t * c1, context_struct_t * c2) { return ((c1->user == c2->user) && (c1->role == c2->role) && (c1->type == c2->type) && mls_context_cmp(c1, c2)); } #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/ebitmap.h0100644 0000000 0000000 00000006150 13756670065 017603 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * An extensible bitmap is a bitmap that supports an * arbitrary number of bits. Extensible bitmaps are * used to represent sets of values, such as types, * roles, categories, and classes. * * Each extensible bitmap is implemented as a linked * list of bitmap nodes, where each bitmap node has * an explicitly specified starting bit position within * the total bitmap. */ #ifndef _SEPOL_POLICYDB_EBITMAP_H_ #define _SEPOL_POLICYDB_EBITMAP_H_ #include #include #ifdef __cplusplus extern "C" { #endif #define MAPTYPE uint64_t /* portion of bitmap in each node */ #define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ #define MAPBIT 1ULL /* a bit in the node bitmap */ typedef struct ebitmap_node { uint32_t startbit; /* starting position in the total bitmap */ MAPTYPE map; /* this node's portion of the bitmap */ struct ebitmap_node *next; } ebitmap_node_t; typedef struct ebitmap { ebitmap_node_t *node; /* first node in the bitmap */ uint32_t highbit; /* highest position in the total bitmap */ } ebitmap_t; #define ebitmap_length(e) ((e)->highbit) #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) #define ebitmap_startnode(e) ((e)->node) static inline unsigned int ebitmap_start(const ebitmap_t * e, ebitmap_node_t ** n) { *n = e->node; return ebitmap_startbit(e); } static inline void ebitmap_init(ebitmap_t * e) { memset(e, 0, sizeof(*e)); } static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit) { if ((bit == ((*n)->startbit + MAPSIZE - 1)) && (*n)->next) { *n = (*n)->next; return (*n)->startbit; } return (bit + 1); } static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit) { if (n->map & (MAPBIT << (bit - n->startbit))) return 1; return 0; } #define ebitmap_for_each_bit(e, n, bit) \ for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \ extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1); extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2); extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2); extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit); extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit); extern unsigned int ebitmap_cardinality(ebitmap_t *e1); extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2); extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src); extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit); extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); extern void ebitmap_destroy(ebitmap_t * e); extern int ebitmap_read(ebitmap_t * e, void *fp); #ifdef __cplusplus } #endif #endif /* _EBITMAP_H_ */ /* FLASK */ libsepol/include/sepol/policydb/expand.h0100644 0000000 0000000 00000007110 13756670065 017436 0ustar000000000 0000000 /* Authors: Jason Tang * Joshua Brindle * Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal items. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_EXPAND_H #define _SEPOL_POLICYDB_EXPAND_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Expand only the avrules for a module. It is valid for this function * to expand base into itself (i.e. base == out); the typemap for * this special case should map type[i] to i+1. Likewise the boolmap * should map bool[i] to i + 1. This function optionally expands * neverallow rules. If neverallow rules are expanded, there is no * need to copy them and doing so could cause duplicate entries when * base == out. If the neverallow rules are not expanded, they are * just copied to the destination policy so that assertion checking * can be performed after expand. No assertion or hierarchy checking * is performed by this function. */ extern int expand_module_avrules(sepol_handle_t * handle, policydb_t * base, policydb_t * out, uint32_t * typemap, uint32_t * boolmap, uint32_t * rolemap, uint32_t * usermap, int verbose, int expand_neverallow); /* * Expand all parts of a module. Neverallow rules are not expanded (only * copied). It is not valid to expand base into itself. If check is non-zero, * performs hierarchy and assertion checking. */ extern int expand_module(sepol_handle_t * handle, policydb_t * base, policydb_t * out, int verbose, int check); extern int convert_type_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * typemap); extern int expand_convert_type_set(policydb_t * p, uint32_t * typemap, type_set_t * set, ebitmap_t * types, unsigned char alwaysexpand); extern int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, unsigned char alwaysexpand); extern int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap); extern int mls_semantic_level_expand(mls_semantic_level_t *sl, mls_level_t *l, policydb_t *p, sepol_handle_t *h); extern int mls_semantic_range_expand(mls_semantic_range_t *sr, mls_range_t *r, policydb_t *p, sepol_handle_t *h); extern int expand_rule(sepol_handle_t * handle, policydb_t * source_pol, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled); extern int expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa); extern int expand_cond_av_list(policydb_t * p, cond_av_list_t * l, cond_av_list_t ** newl, avtab_t * expa); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/flask.h0100644 0000000 0000000 00000011600 13756670065 017256 0ustar000000000 0000000 /* This file is automatically generated. Do not edit. */ #ifndef _SEPOL_POLICYDB_FLASK_H_ #define _SEPOL_POLICYDB_FLASK_H_ /* * Security object class definitions */ #define SECCLASS_SECURITY 1 #define SECCLASS_PROCESS 2 #define SECCLASS_SYSTEM 3 #define SECCLASS_CAPABILITY 4 #define SECCLASS_FILESYSTEM 5 #define SECCLASS_FILE 6 #define SECCLASS_DIR 7 #define SECCLASS_FD 8 #define SECCLASS_LNK_FILE 9 #define SECCLASS_CHR_FILE 10 #define SECCLASS_BLK_FILE 11 #define SECCLASS_SOCK_FILE 12 #define SECCLASS_FIFO_FILE 13 #define SECCLASS_SOCKET 14 #define SECCLASS_TCP_SOCKET 15 #define SECCLASS_UDP_SOCKET 16 #define SECCLASS_RAWIP_SOCKET 17 #define SECCLASS_NODE 18 #define SECCLASS_NETIF 19 #define SECCLASS_NETLINK_SOCKET 20 #define SECCLASS_PACKET_SOCKET 21 #define SECCLASS_KEY_SOCKET 22 #define SECCLASS_UNIX_STREAM_SOCKET 23 #define SECCLASS_UNIX_DGRAM_SOCKET 24 #define SECCLASS_SEM 25 #define SECCLASS_MSG 26 #define SECCLASS_MSGQ 27 #define SECCLASS_SHM 28 #define SECCLASS_IPC 29 #define SECCLASS_PASSWD 30 #define SECCLASS_DRAWABLE 31 #define SECCLASS_WINDOW 32 #define SECCLASS_GC 33 #define SECCLASS_FONT 34 #define SECCLASS_COLORMAP 35 #define SECCLASS_PROPERTY 36 #define SECCLASS_CURSOR 37 #define SECCLASS_XCLIENT 38 #define SECCLASS_XINPUT 39 #define SECCLASS_XSERVER 40 #define SECCLASS_XEXTENSION 41 #define SECCLASS_PAX 42 #define SECCLASS_NETLINK_ROUTE_SOCKET 43 #define SECCLASS_NETLINK_FIREWALL_SOCKET 44 #define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 #define SECCLASS_NETLINK_NFLOG_SOCKET 46 #define SECCLASS_NETLINK_XFRM_SOCKET 47 #define SECCLASS_NETLINK_SELINUX_SOCKET 48 #define SECCLASS_NETLINK_AUDIT_SOCKET 49 #define SECCLASS_NETLINK_IP6FW_SOCKET 50 #define SECCLASS_NETLINK_DNRT_SOCKET 51 #define SECCLASS_DBUS 52 /* * Security identifier indices for initial entities */ #define SECINITSID_KERNEL 1 #define SECINITSID_SECURITY 2 #define SECINITSID_UNLABELED 3 #define SECINITSID_FS 4 #define SECINITSID_FILE 5 #define SECINITSID_FILE_LABELS 6 #define SECINITSID_INIT 7 #define SECINITSID_ANY_SOCKET 8 #define SECINITSID_PORT 9 #define SECINITSID_NETIF 10 #define SECINITSID_NETMSG 11 #define SECINITSID_NODE 12 #define SECINITSID_IGMP_PACKET 13 #define SECINITSID_ICMP_SOCKET 14 #define SECINITSID_TCP_SOCKET 15 #define SECINITSID_SYSCTL_MODPROBE 16 #define SECINITSID_SYSCTL 17 #define SECINITSID_SYSCTL_FS 18 #define SECINITSID_SYSCTL_KERNEL 19 #define SECINITSID_SYSCTL_NET 20 #define SECINITSID_SYSCTL_NET_UNIX 21 #define SECINITSID_SYSCTL_VM 22 #define SECINITSID_SYSCTL_DEV 23 #define SECINITSID_KMOD 24 #define SECINITSID_POLICY 25 #define SECINITSID_SCMP_PACKET 26 #define SECINITSID_DEVNULL 27 #define SECINITSID_NUM 27 #endif libsepol/include/sepol/policydb/flask_types.h0100644 0000000 0000000 00000003363 13756670065 020511 0ustar000000000 0000000 /* -*- linux-c -*- */ /* * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_FLASK_TYPES_H_ #define _SEPOL_POLICYDB_FLASK_TYPES_H_ /* * The basic Flask types and constants. */ #include #include #ifdef __cplusplus extern "C" { #endif /* * A security context is a set of security attributes * associated with each subject and object controlled * by the security policy. The security context type * is defined as a variable-length string that can be * interpreted by any application or user with an * understanding of the security policy. */ typedef char *sepol_security_context_t; /* * An access vector (AV) is a collection of related permissions * for a pair of SIDs. The bits within an access vector * are interpreted differently depending on the class of * the object. The access vector interpretations are specified * in flask/access_vectors, and the corresponding constants * for permissions are defined in the automatically generated * header file av_permissions.h. */ typedef uint32_t sepol_access_vector_t; /* * Each object class is identified by a fixed-size value. * The set of security classes is specified in flask/security_classes, * with the corresponding constants defined in the automatically * generated header file flask.h. */ typedef uint16_t sepol_security_class_t; #define SEPOL_SECCLASS_NULL 0x0000 /* no class */ #define SELINUX_MAGIC 0xf97cff8c #define SELINUX_MOD_MAGIC 0xf97cff8d typedef uint32_t sepol_security_id_t; #define SEPOL_SECSID_NULL 0 struct sepol_av_decision { sepol_access_vector_t allowed; sepol_access_vector_t decided; sepol_access_vector_t auditallow; sepol_access_vector_t auditdeny; uint32_t seqno; }; #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/hashtab.h0100644 0000000 0000000 00000010450 13756670065 017572 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A hash table (hashtab) maintains associations between * key values and datum values. The type of the key values * and the type of the datum values is arbitrary. The * functions for hash computation and key comparison are * provided by the creator of the table. */ #ifndef _SEPOL_POLICYDB_HASHTAB_H_ #define _SEPOL_POLICYDB_HASHTAB_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif typedef char *hashtab_key_t; /* generic key type */ typedef const char *const_hashtab_key_t; /* constant generic key type */ typedef void *hashtab_datum_t; /* generic datum type */ typedef struct hashtab_node *hashtab_ptr_t; typedef struct hashtab_node { hashtab_key_t key; hashtab_datum_t datum; hashtab_ptr_t next; } hashtab_node_t; typedef struct hashtab_val { hashtab_ptr_t *htable; /* hash table */ unsigned int size; /* number of slots in hash table */ uint32_t nel; /* number of elements in hash table */ unsigned int (*hash_value) (struct hashtab_val * h, const_hashtab_key_t key); /* hash function */ int (*keycmp) (struct hashtab_val * h, const_hashtab_key_t key1, const_hashtab_key_t key2); /* key comparison function */ } hashtab_val_t; typedef hashtab_val_t *hashtab_t; /* Creates a new hash table with the specified characteristics. Returns NULL if insufficent space is available or the new hash table otherwise. */ extern hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size); /* Inserts the specified (key, datum) pair into the specified hash table. Returns SEPOL_ENOMEM if insufficient space is available or SEPOL_EEXIST if there is already an entry with the same key or SEPOL_OK otherwise. */ extern int hashtab_insert(hashtab_t h, hashtab_key_t k, hashtab_datum_t d); /* Removes the entry with the specified key from the hash table. Applies the specified destroy function to (key,datum,args) for the entry. Returns SEPOL_ENOENT if no entry has the specified key or SEPOL_OK otherwise. */ extern int hashtab_remove(hashtab_t h, hashtab_key_t k, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Insert or replace the specified (key, datum) pair in the specified hash table. If an entry for the specified key already exists, then the specified destroy function is applied to (key,datum,args) for the entry prior to replacing the entry's contents. Returns SEPOL_ENOMEM if insufficient space is available or SEPOL_OK otherwise. */ extern int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Searches for the entry with the specified key in the hash table. Returns NULL if no entry has the specified key or the datum of the entry otherwise. */ extern hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t k); /* Destroys the specified hash table. */ extern void hashtab_destroy(hashtab_t h); /* Applies the specified apply function to (key,datum,args) for each entry in the specified hash table. The order in which the function is applied to the entries is dependent upon the internal structure of the hash table. If apply returns a non-zero status, then hashtab_map will cease iterating through the hash table and will propagate the error return to its caller. */ extern int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Same as hashtab_map, except that if apply returns a non-zero status, then the (key,datum) pair will be removed from the hashtab and the destroy function will be applied to (key,datum,args). */ extern void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); extern void hashtab_hash_eval(hashtab_t h, char *tag); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/hierarchy.h0100644 0000000 0000000 00000003432 13756670065 020140 0ustar000000000 0000000 /* Authors: Jason Tang * Joshua Brindle * Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal items. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_HIERARCHY_H_ #define _SEPOL_POLICYDB_HIERARCHY_H_ #include #include #ifdef __cplusplus extern "C" { #endif extern int hierarchy_add_bounds(sepol_handle_t *handle, policydb_t *p); extern void bounds_destroy_bad(avtab_ptr_t cur); extern int bounds_check_type(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad); extern int bounds_check_users(sepol_handle_t *handle, policydb_t *p); extern int bounds_check_roles(sepol_handle_t *handle, policydb_t *p); extern int bounds_check_types(sepol_handle_t *handle, policydb_t *p); extern int hierarchy_check_constraints(sepol_handle_t * handle, policydb_t * p); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/link.h0100644 0000000 0000000 00000001005 13756670065 017111 0ustar000000000 0000000 /* Authors: Jason Tang * Joshua Brindle * Karl MacMillan */ #ifndef _SEPOL_POLICYDB_LINK_H #define _SEPOL_POLICYDB_LINK_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif extern int link_modules(sepol_handle_t * handle, policydb_t * b, policydb_t ** mods, int len, int verbose); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/mls_types.h0100644 0000000 0000000 00000010430 13756670065 020175 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Type definitions for the multi-level security (MLS) policy. */ #ifndef _SEPOL_POLICYDB_MLS_TYPES_H_ #define _SEPOL_POLICYDB_MLS_TYPES_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct mls_level { uint32_t sens; /* sensitivity */ ebitmap_t cat; /* category set */ } mls_level_t; typedef struct mls_range { mls_level_t level[2]; /* low == level[0], high == level[1] */ } mls_range_t; static inline int mls_level_cpy(struct mls_level *dst, struct mls_level *src) { dst->sens = src->sens; if (ebitmap_cpy(&dst->cat, &src->cat) < 0) return -1; return 0; } static inline void mls_level_init(struct mls_level *level) { memset(level, 0, sizeof(mls_level_t)); } static inline void mls_level_destroy(struct mls_level *level) { if (level == NULL) return; ebitmap_destroy(&level->cat); mls_level_init(level); } static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2) { return ((l1->sens == l2->sens) && ebitmap_cmp(&l1->cat, &l2->cat)); } static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2) { return ((l1->sens >= l2->sens) && ebitmap_contains(&l1->cat, &l2->cat)); } #define mls_level_incomp(l1, l2) \ (!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1))) #define mls_level_between(l1, l2, l3) \ (mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1))) #define mls_range_contains(r1, r2) \ (mls_level_dom(&(r2).level[0], &(r1).level[0]) && \ mls_level_dom(&(r1).level[1], &(r2).level[1])) static inline int mls_range_cpy(mls_range_t * dst, mls_range_t * src) { if (mls_level_cpy(&dst->level[0], &src->level[0]) < 0) goto err; if (mls_level_cpy(&dst->level[1], &src->level[1]) < 0) goto err_destroy; return 0; err_destroy: mls_level_destroy(&dst->level[0]); err: return -1; } static inline void mls_range_init(struct mls_range *r) { mls_level_init(&r->level[0]); mls_level_init(&r->level[1]); } static inline void mls_range_destroy(struct mls_range *r) { mls_level_destroy(&r->level[0]); mls_level_destroy(&r->level[1]); } static inline int mls_range_eq(struct mls_range *r1, struct mls_range *r2) { return (mls_level_eq(&r1->level[0], &r2->level[0]) && mls_level_eq(&r1->level[1], &r2->level[1])); } typedef struct mls_semantic_cat { uint32_t low; /* first bit this struct represents */ uint32_t high; /* last bit represented - equals low for a single cat */ struct mls_semantic_cat *next; } mls_semantic_cat_t; typedef struct mls_semantic_level { uint32_t sens; mls_semantic_cat_t *cat; } mls_semantic_level_t; typedef struct mls_semantic_range { mls_semantic_level_t level[2]; } mls_semantic_range_t; extern void mls_semantic_cat_init(mls_semantic_cat_t *c); extern void mls_semantic_cat_destroy(mls_semantic_cat_t *c); extern void mls_semantic_level_init(mls_semantic_level_t *l); extern void mls_semantic_level_destroy(mls_semantic_level_t *l); extern int mls_semantic_level_cpy(mls_semantic_level_t *dst, mls_semantic_level_t *src); extern void mls_semantic_range_init(mls_semantic_range_t *r); extern void mls_semantic_range_destroy(mls_semantic_range_t *r); extern int mls_semantic_range_cpy(mls_semantic_range_t *dst, mls_semantic_range_t *src); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/module.h0100644 0000000 0000000 00000002774 13756670065 017457 0ustar000000000 0000000 /* Author: Karl MacMillan * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_MODULE_H_ #define _SEPOL_POLICYDB_MODULE_H_ #include #include #include #include #include #define SEPOL_MODULE_PACKAGE_MAGIC 0xf97cff8f #ifdef __cplusplus extern "C" { #endif struct sepol_module_package { sepol_policydb_t *policy; uint32_t version; char *file_contexts; size_t file_contexts_len; char *seusers; size_t seusers_len; char *user_extra; size_t user_extra_len; char *netfilter_contexts; size_t netfilter_contexts_len; }; extern int sepol_module_package_init(sepol_module_package_t * p); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/polcaps.h0100644 0000000 0000000 00000001321 13756670065 017616 0ustar000000000 0000000 #ifndef _SEPOL_POLICYDB_POLCAPS_H_ #define _SEPOL_POLICYDB_POLCAPS_H_ #ifdef __cplusplus extern "C" { #endif /* Policy capabilities */ enum { POLICYDB_CAPABILITY_NETPEER, POLICYDB_CAPABILITY_OPENPERM, POLICYDB_CAPABILITY_EXTSOCKCLASS, POLICYDB_CAPABILITY_ALWAYSNETWORK, POLICYDB_CAPABILITY_CGROUPSECLABEL, POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION, __POLICYDB_CAPABILITY_MAX }; #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) /* Convert a capability name to number. */ extern int sepol_polcap_getnum(const char *name); /* Convert a capability number to name. */ extern const char *sepol_polcap_getname(unsigned int capnum); #ifdef __cplusplus } #endif #endif /* _SEPOL_POLICYDB_POLCAPS_H_ */ libsepol/include/sepol/policydb/policydb.h0100644 0000000 0000000 00000062570 13756670065 017777 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Joshua Brindle * Karl MacMillan * Jason Tang * * Module support * * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2003 - 2004 Red Hat, Inc. * Copyright (C) 2017 Mellanox Techonolgies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * A policy database (policydb) specifies the * configuration data for the security policy. */ #ifndef _SEPOL_POLICYDB_POLICYDB_H_ #define _SEPOL_POLICYDB_POLICYDB_H_ #include #include #include #include #include #include #include #include #include #define ERRMSG_LEN 1024 #define POLICYDB_SUCCESS 0 #define POLICYDB_ERROR -1 #define POLICYDB_UNSUPPORTED -2 #ifdef __cplusplus extern "C" { #endif #define IB_DEVICE_NAME_MAX 64 /* * A datum type is defined for each kind of symbol * in the configuration data: individual permissions, * common prefixes for access vectors, classes, * users, roles, types, sensitivities, categories, etc. */ /* type set preserves data needed by modules such as *, ~ and attributes */ typedef struct type_set { ebitmap_t types; ebitmap_t negset; #define TYPE_STAR 1 #define TYPE_COMP 2 uint32_t flags; } type_set_t; typedef struct role_set { ebitmap_t roles; #define ROLE_STAR 1 #define ROLE_COMP 2 uint32_t flags; } role_set_t; /* Permission attributes */ typedef struct perm_datum { symtab_datum_t s; } perm_datum_t; /* Attributes of a common prefix for access vectors */ typedef struct common_datum { symtab_datum_t s; symtab_t permissions; /* common permissions */ } common_datum_t; /* Class attributes */ typedef struct class_datum { symtab_datum_t s; char *comkey; /* common name */ common_datum_t *comdatum; /* common datum */ symtab_t permissions; /* class-specific permission symbol table */ constraint_node_t *constraints; /* constraints on class permissions */ constraint_node_t *validatetrans; /* special transition rules */ /* Options how a new object user and role should be decided */ #define DEFAULT_SOURCE 1 #define DEFAULT_TARGET 2 char default_user; char default_role; char default_type; /* Options how a new object range should be decided */ #define DEFAULT_SOURCE_LOW 1 #define DEFAULT_SOURCE_HIGH 2 #define DEFAULT_SOURCE_LOW_HIGH 3 #define DEFAULT_TARGET_LOW 4 #define DEFAULT_TARGET_HIGH 5 #define DEFAULT_TARGET_LOW_HIGH 6 char default_range; } class_datum_t; /* Role attributes */ typedef struct role_datum { symtab_datum_t s; ebitmap_t dominates; /* set of roles dominated by this role */ type_set_t types; /* set of authorized types for role */ ebitmap_t cache; /* This is an expanded set used for context validation during parsing */ uint32_t bounds; /* bounds role, if exist */ #define ROLE_ROLE 0 /* regular role in kernel policies */ #define ROLE_ATTRIB 1 /* attribute */ uint32_t flavor; ebitmap_t roles; /* roles with this attribute */ } role_datum_t; typedef struct role_trans { uint32_t role; /* current role */ uint32_t type; /* program executable type, or new object type */ uint32_t tclass; /* process class, or new object class */ uint32_t new_role; /* new role */ struct role_trans *next; } role_trans_t; typedef struct role_allow { uint32_t role; /* current role */ uint32_t new_role; /* new role */ struct role_allow *next; } role_allow_t; /* filename_trans rules */ typedef struct filename_trans { uint32_t stype; uint32_t ttype; uint32_t tclass; char *name; } filename_trans_t; typedef struct filename_trans_datum { uint32_t otype; /* expected of new object */ } filename_trans_datum_t; /* Type attributes */ typedef struct type_datum { symtab_datum_t s; uint32_t primary; /* primary name? can be set to primary value if below is TYPE_ */ #define TYPE_TYPE 0 /* regular type or alias in kernel policies */ #define TYPE_ATTRIB 1 /* attribute */ #define TYPE_ALIAS 2 /* alias in modular policy */ uint32_t flavor; ebitmap_t types; /* types with this attribute */ #define TYPE_FLAGS_PERMISSIVE (1 << 0) #define TYPE_FLAGS_EXPAND_ATTR_TRUE (1 << 1) #define TYPE_FLAGS_EXPAND_ATTR_FALSE (1 << 2) #define TYPE_FLAGS_EXPAND_ATTR (TYPE_FLAGS_EXPAND_ATTR_TRUE | \ TYPE_FLAGS_EXPAND_ATTR_FALSE) uint32_t flags; uint32_t bounds; /* bounds type, if exist */ } type_datum_t; /* * Properties of type_datum * available on the policy version >= (MOD_)POLICYDB_VERSION_BOUNDARY */ #define TYPEDATUM_PROPERTY_PRIMARY 0x0001 #define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002 #define TYPEDATUM_PROPERTY_ALIAS 0x0004 /* userspace only */ #define TYPEDATUM_PROPERTY_PERMISSIVE 0x0008 /* userspace only */ /* User attributes */ typedef struct user_datum { symtab_datum_t s; role_set_t roles; /* set of authorized roles for user */ mls_semantic_range_t range; /* MLS range (min. - max.) for user */ mls_semantic_level_t dfltlevel; /* default login MLS level for user */ ebitmap_t cache; /* This is an expanded set used for context validation during parsing */ mls_range_t exp_range; /* expanded range used for validation */ mls_level_t exp_dfltlevel; /* expanded range used for validation */ uint32_t bounds; /* bounds user, if exist */ } user_datum_t; /* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */ unsigned char isalias; /* is this sensitivity an alias for another? */ unsigned char defined; } level_datum_t; /* Category attributes */ typedef struct cat_datum { symtab_datum_t s; unsigned char isalias; /* is this category an alias for another? */ } cat_datum_t; typedef struct range_trans { uint32_t source_type; uint32_t target_type; uint32_t target_class; } range_trans_t; /* Boolean data type */ typedef struct cond_bool_datum { symtab_datum_t s; int state; #define COND_BOOL_FLAGS_TUNABLE 0x01 /* is this a tunable? */ uint32_t flags; } cond_bool_datum_t; struct cond_node; typedef struct cond_node cond_list_t; struct cond_av_list; typedef struct class_perm_node { uint32_t tclass; uint32_t data; /* permissions or new type */ struct class_perm_node *next; } class_perm_node_t; #define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) #define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f))) #define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f))) #define EXTENDED_PERMS_LEN 8 typedef struct av_extended_perms { #define AVRULE_XPERMS_IOCTLFUNCTION 0x01 #define AVRULE_XPERMS_IOCTLDRIVER 0x02 uint8_t specified; uint8_t driver; /* 256 bits of permissions */ uint32_t perms[EXTENDED_PERMS_LEN]; } av_extended_perms_t; typedef struct avrule { /* these typedefs are almost exactly the same as those in avtab.h - they are * here because of the need to include neverallow and dontaudit messages */ #define AVRULE_ALLOWED AVTAB_ALLOWED #define AVRULE_AUDITALLOW AVTAB_AUDITALLOW #define AVRULE_AUDITDENY AVTAB_AUDITDENY #define AVRULE_DONTAUDIT 0x0008 #define AVRULE_NEVERALLOW AVTAB_NEVERALLOW #define AVRULE_AV (AVRULE_ALLOWED | AVRULE_AUDITALLOW | AVRULE_AUDITDENY | AVRULE_DONTAUDIT | AVRULE_NEVERALLOW) #define AVRULE_TRANSITION AVTAB_TRANSITION #define AVRULE_MEMBER AVTAB_MEMBER #define AVRULE_CHANGE AVTAB_CHANGE #define AVRULE_TYPE (AVRULE_TRANSITION | AVRULE_MEMBER | AVRULE_CHANGE) #define AVRULE_XPERMS_ALLOWED AVTAB_XPERMS_ALLOWED #define AVRULE_XPERMS_AUDITALLOW AVTAB_XPERMS_AUDITALLOW #define AVRULE_XPERMS_DONTAUDIT AVTAB_XPERMS_DONTAUDIT #define AVRULE_XPERMS_NEVERALLOW AVTAB_XPERMS_NEVERALLOW #define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \ AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW) uint32_t specified; #define RULE_SELF 1 uint32_t flags; type_set_t stypes; type_set_t ttypes; class_perm_node_t *perms; av_extended_perms_t *xperms; unsigned long line; /* line number from policy.conf where * this rule originated */ /* source file name and line number (e.g. .te file) */ char *source_filename; unsigned long source_line; struct avrule *next; } avrule_t; typedef struct role_trans_rule { role_set_t roles; /* current role */ type_set_t types; /* program executable type, or new object type */ ebitmap_t classes; /* process class, or new object class */ uint32_t new_role; /* new role */ struct role_trans_rule *next; } role_trans_rule_t; typedef struct role_allow_rule { role_set_t roles; /* current role */ role_set_t new_roles; /* new roles */ struct role_allow_rule *next; } role_allow_rule_t; typedef struct filename_trans_rule { type_set_t stypes; type_set_t ttypes; uint32_t tclass; char *name; uint32_t otype; /* new type */ struct filename_trans_rule *next; } filename_trans_rule_t; typedef struct range_trans_rule { type_set_t stypes; type_set_t ttypes; ebitmap_t tclasses; mls_semantic_range_t trange; struct range_trans_rule *next; } range_trans_rule_t; /* * The configuration data includes security contexts for * initial SIDs, unlabeled file systems, TCP and UDP port numbers, * network interfaces, and nodes. This structure stores the * relevant data for one such entry. Entries of the same kind * (e.g. all initial SIDs) are linked together into a list. */ typedef struct ocontext { union { char *name; /* name of initial SID, fs, netif, fstype, path */ struct { uint8_t protocol; uint16_t low_port; uint16_t high_port; } port; /* TCP or UDP port information */ struct { uint32_t addr; /* network order */ uint32_t mask; /* network order */ } node; /* node information */ struct { uint32_t addr[4]; /* network order */ uint32_t mask[4]; /* network order */ } node6; /* IPv6 node information */ uint32_t device; uint16_t pirq; struct { uint64_t low_iomem; uint64_t high_iomem; } iomem; struct { uint32_t low_ioport; uint32_t high_ioport; } ioport; struct { uint64_t subnet_prefix; uint16_t low_pkey; uint16_t high_pkey; } ibpkey; struct { char *dev_name; uint8_t port; } ibendport; } u; union { uint32_t sclass; /* security class for genfs */ uint32_t behavior; /* labeling behavior for fs_use */ } v; context_struct_t context[2]; /* security context(s) */ sepol_security_id_t sid[2]; /* SID(s) */ struct ocontext *next; } ocontext_t; typedef struct genfs { char *fstype; struct ocontext *head; struct genfs *next; } genfs_t; /* symbol table array indices */ #define SYM_COMMONS 0 #define SYM_CLASSES 1 #define SYM_ROLES 2 #define SYM_TYPES 3 #define SYM_USERS 4 #define SYM_BOOLS 5 #define SYM_LEVELS 6 #define SYM_CATS 7 #define SYM_NUM 8 /* object context array indices */ #define OCON_ISID 0 /* initial SIDs */ #define OCON_FS 1 /* unlabeled file systems */ #define OCON_PORT 2 /* TCP and UDP port numbers */ #define OCON_NETIF 3 /* network interfaces */ #define OCON_NODE 4 /* nodes */ #define OCON_FSUSE 5 /* fs_use */ #define OCON_NODE6 6 /* IPv6 nodes */ #define OCON_IBPKEY 7 /* Infiniband PKEY */ #define OCON_IBENDPORT 8 /* Infiniband End Port */ /* object context array indices for Xen */ #define OCON_XEN_ISID 0 /* initial SIDs */ #define OCON_XEN_PIRQ 1 /* physical irqs */ #define OCON_XEN_IOPORT 2 /* io ports */ #define OCON_XEN_IOMEM 3 /* io memory */ #define OCON_XEN_PCIDEVICE 4 /* pci devices */ #define OCON_XEN_DEVICETREE 5 /* device tree node */ /* OCON_NUM needs to be the largest index in any platform's ocontext array */ #define OCON_NUM 9 /* section: module information */ /* scope_index_t holds all of the symbols that are in scope in a * particular situation. The bitmaps are indices (and thus must * subtract one) into the global policydb->scope array. */ typedef struct scope_index { ebitmap_t scope[SYM_NUM]; #define p_classes_scope scope[SYM_CLASSES] #define p_roles_scope scope[SYM_ROLES] #define p_types_scope scope[SYM_TYPES] #define p_users_scope scope[SYM_USERS] #define p_bools_scope scope[SYM_BOOLS] #define p_sens_scope scope[SYM_LEVELS] #define p_cat_scope scope[SYM_CATS] /* this array maps from class->value to the permissions within * scope. if bit (perm->value - 1) is set in map * class_perms_map[class->value - 1] then that permission is * enabled for this class within this decl. */ ebitmap_t *class_perms_map; /* total number of classes in class_perms_map array */ uint32_t class_perms_len; } scope_index_t; /* a list of declarations for a particular avrule_decl */ /* These two structs declare a block of policy that has TE and RBAC * statements and declarations. The root block (the global policy) * can never have an ELSE branch. */ typedef struct avrule_decl { uint32_t decl_id; uint32_t enabled; /* whether this block is enabled */ cond_list_t *cond_list; avrule_t *avrules; role_trans_rule_t *role_tr_rules; role_allow_rule_t *role_allow_rules; range_trans_rule_t *range_tr_rules; scope_index_t required; /* symbols needed to activate this block */ scope_index_t declared; /* symbols declared within this block */ /* type transition rules with a 'name' component */ filename_trans_rule_t *filename_trans_rules; /* for additive statements (type attribute, roles, and users) */ symtab_t symtab[SYM_NUM]; /* In a linked module this will contain the name of the module * from which this avrule_decl originated. */ char *module_name; struct avrule_decl *next; } avrule_decl_t; typedef struct avrule_block { avrule_decl_t *branch_list; avrule_decl_t *enabled; /* pointer to which branch is enabled. this is used in linking and never written to disk */ #define AVRULE_OPTIONAL 1 uint32_t flags; /* any flags for this block, currently just optional */ struct avrule_block *next; } avrule_block_t; /* Every identifier has its own scope datum. The datum describes if * the item is to be included into the final policy during * expansion. */ typedef struct scope_datum { /* Required for this decl */ #define SCOPE_REQ 1 /* Declared in this decl */ #define SCOPE_DECL 2 uint32_t scope; uint32_t *decl_ids; uint32_t decl_ids_len; /* decl_ids is a list of avrule_decl's that declare/require * this symbol. If scope==SCOPE_DECL then this is a list of * declarations. If the symbol may only be declared once * (types, bools) then decl_ids_len will be exactly 1. For * implicitly declared things (roles, users) then decl_ids_len * will be at least 1. */ } scope_datum_t; /* The policy database */ typedef struct policydb { #define POLICY_KERN SEPOL_POLICY_KERN #define POLICY_BASE SEPOL_POLICY_BASE #define POLICY_MOD SEPOL_POLICY_MOD uint32_t policy_type; char *name; char *version; int target_platform; /* Set when the policydb is modified such that writing is unsupported */ int unsupported_format; /* Whether this policydb is mls, should always be set */ int mls; /* symbol tables */ symtab_t symtab[SYM_NUM]; #define p_commons symtab[SYM_COMMONS] #define p_classes symtab[SYM_CLASSES] #define p_roles symtab[SYM_ROLES] #define p_types symtab[SYM_TYPES] #define p_users symtab[SYM_USERS] #define p_bools symtab[SYM_BOOLS] #define p_levels symtab[SYM_LEVELS] #define p_cats symtab[SYM_CATS] /* symbol names indexed by (value - 1) */ char **sym_val_to_name[SYM_NUM]; #define p_common_val_to_name sym_val_to_name[SYM_COMMONS] #define p_class_val_to_name sym_val_to_name[SYM_CLASSES] #define p_role_val_to_name sym_val_to_name[SYM_ROLES] #define p_type_val_to_name sym_val_to_name[SYM_TYPES] #define p_user_val_to_name sym_val_to_name[SYM_USERS] #define p_bool_val_to_name sym_val_to_name[SYM_BOOLS] #define p_sens_val_to_name sym_val_to_name[SYM_LEVELS] #define p_cat_val_to_name sym_val_to_name[SYM_CATS] /* class, role, and user attributes indexed by (value - 1) */ class_datum_t **class_val_to_struct; role_datum_t **role_val_to_struct; user_datum_t **user_val_to_struct; type_datum_t **type_val_to_struct; /* module stuff section -- used in parsing and for modules */ /* keep track of the scope for every identifier. these are * hash tables, where the key is the identifier name and value * a scope_datum_t. as a convenience, one may use the * p_*_macros (cf. struct scope_index_t declaration). */ symtab_t scope[SYM_NUM]; /* module rule storage */ avrule_block_t *global; /* avrule_decl index used for link/expand */ avrule_decl_t **decl_val_to_struct; /* compiled storage of rules - use for the kernel policy */ /* type enforcement access vectors and transitions */ avtab_t te_avtab; /* bools indexed by (value - 1) */ cond_bool_datum_t **bool_val_to_struct; /* type enforcement conditional access vectors and transitions */ avtab_t te_cond_avtab; /* linked list indexing te_cond_avtab by conditional */ cond_list_t *cond_list; /* role transitions */ role_trans_t *role_tr; /* role allows */ role_allow_t *role_allow; /* security contexts of initial SIDs, unlabeled file systems, TCP or UDP port numbers, network interfaces and nodes */ ocontext_t *ocontexts[OCON_NUM]; /* security contexts for files in filesystems that cannot support a persistent label mapping or use another fixed labeling behavior. */ genfs_t *genfs; /* range transitions table (range_trans_key -> mls_range) */ hashtab_t range_tr; /* file transitions with the last path component */ hashtab_t filename_trans; ebitmap_t *type_attr_map; ebitmap_t *attr_type_map; /* not saved in the binary policy */ ebitmap_t policycaps; /* this bitmap is referenced by type NOT the typical type-1 used in other bitmaps. Someday the 0 bit may be used for global permissive */ ebitmap_t permissive_map; unsigned policyvers; unsigned handle_unknown; } policydb_t; struct sepol_policydb { struct policydb p; }; extern int policydb_init(policydb_t * p); extern int policydb_from_image(sepol_handle_t * handle, void *data, size_t len, policydb_t * policydb); extern int policydb_to_image(sepol_handle_t * handle, policydb_t * policydb, void **newdata, size_t * newlen); extern int policydb_index_classes(policydb_t * p); extern int policydb_index_bools(policydb_t * p); extern int policydb_index_others(sepol_handle_t * handle, policydb_t * p, unsigned int verbose); extern int policydb_role_cache(hashtab_key_t key, hashtab_datum_t datum, void *arg); extern int policydb_user_cache(hashtab_key_t key, hashtab_datum_t datum, void *arg); extern int policydb_reindex_users(policydb_t * p); extern void policydb_destroy(policydb_t * p); extern int policydb_load_isids(policydb_t * p, sidtab_t * s); extern int policydb_sort_ocontexts(policydb_t *p); /* Deprecated */ extern int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c); extern void symtabs_destroy(symtab_t * symtab); extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p); extern void class_perm_node_init(class_perm_node_t * x); extern void type_set_init(type_set_t * x); extern void type_set_destroy(type_set_t * x); extern int type_set_cpy(type_set_t * dst, type_set_t * src); extern int type_set_or_eq(type_set_t * dst, type_set_t * other); extern void role_set_init(role_set_t * x); extern void role_set_destroy(role_set_t * x); extern void avrule_init(avrule_t * x); extern void avrule_destroy(avrule_t * x); extern void avrule_list_destroy(avrule_t * x); extern void role_trans_rule_init(role_trans_rule_t * x); extern void role_trans_rule_list_destroy(role_trans_rule_t * x); extern void filename_trans_rule_init(filename_trans_rule_t * x); extern void filename_trans_rule_list_destroy(filename_trans_rule_t * x); extern void role_datum_init(role_datum_t * x); extern void role_datum_destroy(role_datum_t * x); extern void role_allow_rule_init(role_allow_rule_t * x); extern void role_allow_rule_destroy(role_allow_rule_t * x); extern void role_allow_rule_list_destroy(role_allow_rule_t * x); extern void range_trans_rule_init(range_trans_rule_t *x); extern void range_trans_rule_destroy(range_trans_rule_t *x); extern void range_trans_rule_list_destroy(range_trans_rule_t *x); extern void type_datum_init(type_datum_t * x); extern void type_datum_destroy(type_datum_t * x); extern void user_datum_init(user_datum_t * x); extern void user_datum_destroy(user_datum_t * x); extern void level_datum_init(level_datum_t * x); extern void level_datum_destroy(level_datum_t * x); extern void cat_datum_init(cat_datum_t * x); extern void cat_datum_destroy(cat_datum_t * x); extern int check_assertion(policydb_t *p, avrule_t *avrule); extern int check_assertions(sepol_handle_t * handle, policydb_t * p, avrule_t * avrules); extern int symtab_insert(policydb_t * x, uint32_t sym, hashtab_key_t key, hashtab_datum_t datum, uint32_t scope, uint32_t avrule_decl_id, uint32_t * value); /* A policy "file" may be a memory region referenced by a (data, len) pair or a file referenced by a FILE pointer. */ typedef struct policy_file { #define PF_USE_MEMORY 0 #define PF_USE_STDIO 1 #define PF_LEN 2 /* total up length in len field */ unsigned type; char *data; size_t len; size_t size; FILE *fp; struct sepol_handle *handle; } policy_file_t; struct sepol_policy_file { struct policy_file pf; }; extern void policy_file_init(policy_file_t * x); extern int policydb_read(policydb_t * p, struct policy_file *fp, unsigned int verbose); extern int avrule_read_list(policydb_t * p, avrule_t ** avrules, struct policy_file *fp); extern int policydb_write(struct policydb *p, struct policy_file *pf); extern int policydb_set_target_platform(policydb_t *p, int platform); #define PERM_SYMTAB_SIZE 32 /* Identify specific policy version changes */ #define POLICYDB_VERSION_BASE 15 #define POLICYDB_VERSION_BOOL 16 #define POLICYDB_VERSION_IPV6 17 #define POLICYDB_VERSION_NLCLASS 18 #define POLICYDB_VERSION_VALIDATETRANS 19 #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS 21 #define POLICYDB_VERSION_POLCAP 22 #define POLICYDB_VERSION_PERMISSIVE 23 #define POLICYDB_VERSION_BOUNDARY 24 #define POLICYDB_VERSION_FILENAME_TRANS 25 #define POLICYDB_VERSION_ROLETRANS 26 #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 #define POLICYDB_VERSION_DEFAULT_TYPE 28 #define POLICYDB_VERSION_CONSTRAINT_NAMES 29 #define POLICYDB_VERSION_XEN_DEVICETREE 30 /* Xen-specific */ #define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */ #define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */ /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #define POLICYDB_VERSION_MAX POLICYDB_VERSION_INFINIBAND /* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4 #define MOD_POLICYDB_VERSION_VALIDATETRANS 5 #define MOD_POLICYDB_VERSION_MLS 5 #define MOD_POLICYDB_VERSION_RANGETRANS 6 #define MOD_POLICYDB_VERSION_MLS_USERS 6 #define MOD_POLICYDB_VERSION_POLCAP 7 #define MOD_POLICYDB_VERSION_PERMISSIVE 8 #define MOD_POLICYDB_VERSION_BOUNDARY 9 #define MOD_POLICYDB_VERSION_BOUNDARY_ALIAS 10 #define MOD_POLICYDB_VERSION_FILENAME_TRANS 11 #define MOD_POLICYDB_VERSION_ROLETRANS 12 #define MOD_POLICYDB_VERSION_ROLEATTRIB 13 #define MOD_POLICYDB_VERSION_TUNABLE_SEP 14 #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 15 #define MOD_POLICYDB_VERSION_DEFAULT_TYPE 16 #define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES 17 #define MOD_POLICYDB_VERSION_XPERMS_IOCTL 18 #define MOD_POLICYDB_VERSION_INFINIBAND 19 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE #define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_INFINIBAND #define POLICYDB_CONFIG_MLS 1 /* macros to check policy feature */ /* TODO: add other features here */ #define policydb_has_boundary_feature(p) \ (((p)->policy_type == POLICY_KERN \ && p->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ ((p)->policy_type != POLICY_KERN \ && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) /* the config flags related to unknown classes/perms are bits 2 and 3 */ #define DENY_UNKNOWN SEPOL_DENY_UNKNOWN #define REJECT_UNKNOWN SEPOL_REJECT_UNKNOWN #define ALLOW_UNKNOWN SEPOL_ALLOW_UNKNOWN #define POLICYDB_CONFIG_UNKNOWN_MASK (DENY_UNKNOWN | REJECT_UNKNOWN | ALLOW_UNKNOWN) #define OBJECT_R "object_r" #define OBJECT_R_VAL 1 #define POLICYDB_MAGIC SELINUX_MAGIC #define POLICYDB_STRING "SE Linux" #define POLICYDB_XEN_STRING "XenFlask" #define POLICYDB_STRING_MAX_LENGTH 32 #define POLICYDB_MOD_MAGIC SELINUX_MOD_MAGIC #define POLICYDB_MOD_STRING "SE Linux Module" #ifdef __cplusplus } #endif #endif /* _POLICYDB_H_ */ /* FLASK */ libsepol/include/sepol/policydb/services.h0100644 0000000 0000000 00000020607 13756670065 020010 0ustar000000000 0000000 /* -*- linux-c -*- */ /* * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_SERVICES_H_ #define _SEPOL_POLICYDB_SERVICES_H_ /* * Security server interface. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Set the policydb and sidtab structures to be used by the service functions. If not set, then these default to private structures within libsepol that can only be initialized and accessed via the service functions themselves. Setting the structures explicitly allows a program to directly manipulate them, e.g. checkpolicy populates the structures directly from a source policy rather than from a binary policy. */ extern int sepol_set_policydb(policydb_t * p); extern int sepol_set_sidtab(sidtab_t * s); /* Modify a policydb for boolean settings. */ int sepol_genbools_policydb(policydb_t * policydb, const char *booleans); /* Modify a policydb for user settings. */ int sepol_genusers_policydb(policydb_t * policydb, const char *usersdir); /* Load the security policy. This initializes the policydb and sidtab based on the provided binary policy. */ extern int sepol_load_policy(void *data, size_t len); /* * Compute access vectors based on a SID pair for * the permissions in a particular class. */ extern int sepol_compute_av(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_access_vector_t requested, /* IN */ struct sepol_av_decision *avd); /* OUT */ /* Same as above, but also return the reason(s) for any denials of the requested permissions. */ #define SEPOL_COMPUTEAV_TE 0x1U #define SEPOL_COMPUTEAV_CONS 0x2U #define SEPOL_COMPUTEAV_RBAC 0x4U #define SEPOL_COMPUTEAV_BOUNDS 0x8U extern int sepol_compute_av_reason(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason); /* * Same as above, but also returns the constraint expression calculations * whether allowed or denied in a buffer. This buffer is allocated by * this call and must be free'd by the caller using free(3). The contraint * buffer will contain any constraints in infix notation. * If the SHOW_GRANTED flag is set it will show granted and denied * constraints. The default is to show only denied constraints. */ #define SHOW_GRANTED 1 extern int sepol_compute_av_reason_buffer(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **reason_buf, unsigned int flags); /* * Returns the mls/validatetrans constraint expression calculations in * a buffer that must be free'd by the caller using free(3). * If the SHOW_GRANTED flag is set it will show granted and denied * mls/validatetrans (the default is to show only those denied). */ extern int sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid, sepol_security_id_t newsid, sepol_security_id_t tasksid, sepol_security_class_t tclass, char **reason_buf, unsigned int flags); /* * Return a class ID associated with the class string representation * specified by `class_name'. */ extern int sepol_string_to_security_class(const char *class_name, sepol_security_class_t *tclass); /* * Return a permission av bit associated with tclass and the string * representation of the `perm_name'. */ extern int sepol_string_to_av_perm(sepol_security_class_t tclass, const char *perm_name, sepol_access_vector_t *av); /* * Compute a SID to use for labeling a new object in the * class `tclass' based on a SID pair. */ extern int sepol_transition_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Compute a SID to use when selecting a member of a * polyinstantiated object of class `tclass' based on * a SID pair. */ extern int sepol_member_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Compute a SID to use for relabeling an object in the * class `tclass' based on a SID pair. */ extern int sepol_change_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Write the security context string representation of * the context associated with `sid' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ extern int sepol_sid_to_context(sepol_security_id_t sid, /* IN */ sepol_security_context_t * scontext, /* OUT */ size_t * scontext_len); /* OUT */ /* * Return a SID associated with the security context that * has the string representation specified by `scontext'. */ extern int sepol_context_to_sid(const sepol_security_context_t scontext, /* IN */ size_t scontext_len, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Generate the set of SIDs for legal security contexts * for a given user that can be reached by `fromsid'. * Set `*sids' to point to a dynamically allocated * array containing the set of SIDs. Set `*nel' to the * number of elements in the array. */ extern int sepol_get_user_sids(sepol_security_id_t callsid, char *username, sepol_security_id_t ** sids, uint32_t * nel); /* * Return the SIDs to use for an unlabeled file system * that is being mounted from the device with the * the kdevname `name'. The `fs_sid' SID is returned for * the file system and the `file_sid' SID is returned * for all files within that file system. */ extern int sepol_fs_sid(char *dev, /* IN */ sepol_security_id_t * fs_sid, /* OUT */ sepol_security_id_t * file_sid); /* OUT */ /* * Return the SID of the port specified by * `domain', `type', `protocol', and `port'. */ extern int sepol_port_sid(uint16_t domain, uint16_t type, uint8_t protocol, uint16_t port, sepol_security_id_t * out_sid); /* * Return the SID of the ibpkey specified by * `subnet prefix', and `pkey'. */ extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p, uint16_t pkey, sepol_security_id_t *out_sid); /* * Return the SID of the ibendport specified by * `dev_name', and `port'. */ extern int sepol_ibendport_sid(char *dev_name, uint8_t port, sepol_security_id_t *out_sid); /* * Return the SIDs to use for a network interface * with the name `name'. The `if_sid' SID is returned for * the interface and the `msg_sid' SID is returned as * the default SID for messages received on the * interface. */ extern int sepol_netif_sid(char *name, sepol_security_id_t * if_sid, sepol_security_id_t * msg_sid); /* * Return the SID of the node specified by the address * `addr' where `addrlen' is the length of the address * in bytes and `domain' is the communications domain or * address family in which the address should be interpreted. */ extern int sepol_node_sid(uint16_t domain, void *addr, size_t addrlen, sepol_security_id_t * out_sid); /* * Return a value indicating how to handle labeling for the * the specified filesystem type, and optionally return a SID * for the filesystem object. */ #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ #define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ #define SECURITY_FS_USE_NONE 5 /* no labeling support */ extern int sepol_fs_use(const char *fstype, /* IN */ unsigned int *behavior, /* OUT */ sepol_security_id_t * sid); /* OUT */ /* * Return the SID to use for a file in a filesystem * that cannot support a persistent label mapping or use another * fixed labeling behavior like transition SIDs or task SIDs. */ extern int sepol_genfs_sid(const char *fstype, /* IN */ const char *name, /* IN */ sepol_security_class_t sclass, /* IN */ sepol_security_id_t * sid); /* OUT */ #ifdef __cplusplus } #endif #endif libsepol/include/sepol/policydb/sidtab.h0100644 0000000 0000000 00000003670 13756670065 017434 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A security identifier table (sidtab) is a hash table * of security context structures indexed by SID value. */ #ifndef _SEPOL_POLICYDB_SIDTAB_H_ #define _SEPOL_POLICYDB_SIDTAB_H_ #include #ifdef __cplusplus extern "C" { #endif typedef struct sidtab_node { sepol_security_id_t sid; /* security identifier */ context_struct_t context; /* security context structure */ struct sidtab_node *next; } sidtab_node_t; typedef struct sidtab_node *sidtab_ptr_t; #define SIDTAB_HASH_BITS 7 #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) #define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS typedef struct { sidtab_ptr_t *htable; unsigned int nel; /* number of elements */ unsigned int next_sid; /* next SID to allocate */ unsigned char shutdown; } sidtab_t; extern int sepol_sidtab_init(sidtab_t * s); extern int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid, context_struct_t * context); extern context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid); extern int sepol_sidtab_map(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args); extern void sepol_sidtab_map_remove_on_error(sidtab_t * s, int (*apply) (sepol_security_id_t s, context_struct_t * context, void *args), void *args); extern int sepol_sidtab_context_to_sid(sidtab_t * s, /* IN */ context_struct_t * context, /* IN */ sepol_security_id_t * sid); /* OUT */ extern void sepol_sidtab_hash_eval(sidtab_t * h, char *tag); extern void sepol_sidtab_destroy(sidtab_t * s); extern void sepol_sidtab_set(sidtab_t * dst, sidtab_t * src); extern void sepol_sidtab_shutdown(sidtab_t * s); #ifdef __cplusplus } #endif #endif /* _SIDTAB_H_ */ /* FLASK */ libsepol/include/sepol/policydb/symtab.h0100644 0000000 0000000 00000002116 13756670065 017457 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A symbol table (symtab) maintains associations between symbol * strings and datum values. The type of the datum values * is arbitrary. The symbol table type is implemented * using the hash table type (hashtab). */ #ifndef _SEPOL_POLICYDB_SYMTAB_H_ #define _SEPOL_POLICYDB_SYMTAB_H_ #include #ifdef __cplusplus extern "C" { #endif /* The symtab_datum struct stores the common information for * all symtab datums. It should the first element in every * struct that will be used in a symtab to allow the specific * datum types to be freely cast to this type. * * The values start at 1 - 0 is never a valid value. */ typedef struct symtab_datum { uint32_t value; } symtab_datum_t; typedef struct { hashtab_t table; /* hash table (keyed on a string) */ uint32_t nprim; /* number of primary names in table */ } symtab_t; extern int symtab_init(symtab_t *, unsigned int size); extern void symtab_destroy(symtab_t *); #ifdef __cplusplus } #endif #endif /* _SYMTAB_H_ */ /* FLASK */ libsepol/include/sepol/policydb/util.h0100644 0000000 0000000 00000002665 13756670065 017146 0ustar000000000 0000000 /* Authors: Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal namespaces. * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __SEPOL_UTIL_H__ #define __SEPOL_UTIL_H__ #ifdef __cplusplus extern "C" { #endif extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a); extern char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, sepol_access_vector_t av); char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms); /* * The tokenize function may be used to * replace sscanf */ extern int tokenize(char *line_buf, char delim, int num_args, ...); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/port_record.h0100644 0000000 0000000 00000003737 13756670065 016707 0ustar000000000 0000000 #ifndef _SEPOL_PORT_RECORD_H_ #define _SEPOL_PORT_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_port; struct sepol_port_key; typedef struct sepol_port sepol_port_t; typedef struct sepol_port_key sepol_port_key_t; #define SEPOL_PROTO_UDP 0 #define SEPOL_PROTO_TCP 1 #define SEPOL_PROTO_DCCP 2 #define SEPOL_PROTO_SCTP 3 /* Key */ extern int sepol_port_compare(const sepol_port_t * port, const sepol_port_key_t * key); extern int sepol_port_compare2(const sepol_port_t * port, const sepol_port_t * port2); extern int sepol_port_key_create(sepol_handle_t * handle, int low, int high, int proto, sepol_port_key_t ** key_ptr); extern void sepol_port_key_unpack(const sepol_port_key_t * key, int *low, int *high, int *proto); extern int sepol_port_key_extract(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_key_t ** key_ptr); extern void sepol_port_key_free(sepol_port_key_t * key); /* Protocol */ extern int sepol_port_get_proto(const sepol_port_t * port); extern void sepol_port_set_proto(sepol_port_t * port, int proto); extern const char *sepol_port_get_proto_str(int proto); /* Port */ extern int sepol_port_get_low(const sepol_port_t * port); extern int sepol_port_get_high(const sepol_port_t * port); extern void sepol_port_set_port(sepol_port_t * port, int port_num); extern void sepol_port_set_range(sepol_port_t * port, int low, int high); /* Context */ extern sepol_context_t *sepol_port_get_con(const sepol_port_t * port); extern int sepol_port_set_con(sepol_handle_t * handle, sepol_port_t * port, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port_ptr); extern int sepol_port_clone(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_t ** port_ptr); extern void sepol_port_free(sepol_port_t * port); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/ports.h0100644 0000000 0000000 00000002440 13756670065 015522 0ustar000000000 0000000 #ifndef _SEPOL_PORTS_H_ #define _SEPOL_PORTS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ports */ extern int sepol_port_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if a port exists */ extern int sepol_port_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_port_key_t * key, int *response); /* Query a port - returns the port, or NULL if not found */ extern int sepol_port_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_port_key_t * key, sepol_port_t ** response); /* Modify a port, or add it, if the key is not found */ extern int sepol_port_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_port_key_t * key, const sepol_port_t * data); /* Iterate the ports * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_port_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_port_t * port, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/roles.h0100644 0000000 0000000 00000000523 13756670065 015477 0ustar000000000 0000000 #ifndef _SEPOL_ROLES_H_ #define _SEPOL_ROLES_H_ #ifdef __cplusplus extern "C" { #endif extern int sepol_role_exists(const sepol_policydb_t * policydb, const char *role, int *response); extern int sepol_role_list(const sepol_policydb_t * policydb, char ***roles, unsigned int *nroles); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/sepol.h0100644 0000000 0000000 00000001536 13756670065 015502 0ustar000000000 0000000 #ifndef _SEPOL_H_ #define _SEPOL_H_ #include #include #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Set internal policydb from a file for subsequent service calls. */ extern int sepol_set_policydb_from_file(FILE * fp); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/user_record.h0100644 0000000 0000000 00000004520 13756670065 016670 0ustar000000000 0000000 #ifndef _SEPOL_USER_RECORD_H_ #define _SEPOL_USER_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_user; struct sepol_user_key; typedef struct sepol_user sepol_user_t; typedef struct sepol_user_key sepol_user_key_t; /* Key */ extern int sepol_user_key_create(sepol_handle_t * handle, const char *name, sepol_user_key_t ** key); extern void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name); extern int sepol_user_key_extract(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_key_t ** key_ptr); extern void sepol_user_key_free(sepol_user_key_t * key); extern int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key); extern int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2); /* Name */ extern const char *sepol_user_get_name(const sepol_user_t * user); extern int sepol_user_set_name(sepol_handle_t * handle, sepol_user_t * user, const char *name); /* MLS */ extern const char *sepol_user_get_mlslevel(const sepol_user_t * user); extern int sepol_user_set_mlslevel(sepol_handle_t * handle, sepol_user_t * user, const char *mls_level); extern const char *sepol_user_get_mlsrange(const sepol_user_t * user); extern int sepol_user_set_mlsrange(sepol_handle_t * handle, sepol_user_t * user, const char *mls_range); /* Role management */ extern int sepol_user_get_num_roles(const sepol_user_t * user); extern int sepol_user_add_role(sepol_handle_t * handle, sepol_user_t * user, const char *role); extern void sepol_user_del_role(sepol_user_t * user, const char *role); extern int sepol_user_has_role(const sepol_user_t * user, const char *role); extern int sepol_user_get_roles(sepol_handle_t * handle, const sepol_user_t * user, const char ***roles_arr, unsigned int *num_roles); extern int sepol_user_set_roles(sepol_handle_t * handle, sepol_user_t * user, const char **roles_arr, unsigned int num_roles); /* Create/Clone/Destroy */ extern int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr); extern int sepol_user_clone(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_t ** user_ptr); extern void sepol_user_free(sepol_user_t * user); #ifdef __cplusplus } #endif #endif libsepol/include/sepol/users.h0100644 0000000 0000000 00000003747 13756670065 015527 0ustar000000000 0000000 #ifndef _SEPOL_USERS_H_ #define _SEPOL_USERS_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /*---------compatibility------------*/ /* Given an existing binary policy (starting at 'data with length 'len') and user configurations living in 'usersdir', generate a new binary policy for the new user configurations. Sets '*newdata' and '*newlen' to refer to the new binary policy image. */ extern int sepol_genusers(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen); /* Enable or disable deletion of users by sepol_genusers(3) when a user in original binary policy image is not defined by the new user configurations. Defaults to disabled. */ extern void sepol_set_delusers(int on); /*--------end compatibility----------*/ /* Modify the user, or add it, if the key is not found */ extern int sepol_user_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_user_key_t * key, const sepol_user_t * data); /* Return the number of users */ extern int sepol_user_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if the specified user exists */ extern int sepol_user_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_user_key_t * key, int *response); /* Query a user - returns the user or NULL if not found */ extern int sepol_user_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_user_key_t * key, sepol_user_t ** response); /* Iterate the users * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_user_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_user_t * user, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol/man/0040755 0000000 0000000 00000000000 13756670065 012213 5ustar000000000 0000000 libsepol/man/Makefile0100644 0000000 0000000 00000001413 13756670065 013647 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 MAN8SUBDIR ?= man8 MAN3DIR ?= $(MANDIR)/$(MAN3SUBDIR) MAN8DIR ?= $(MANDIR)/$(MAN8SUBDIR) all: install: all mkdir -p $(DESTDIR)$(MAN3DIR) mkdir -p $(DESTDIR)$(MAN8DIR) install -m 644 man3/*.3 $(DESTDIR)$(MAN3DIR) install -m 644 man8/*.8 $(DESTDIR)$(MAN8DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man3 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ install -m 644 $${lang}/man3/*.3 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ fi ; \ if [ -e $${lang}/man8 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ install -m 644 $${lang}/man8/*.8 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ fi ; \ done libsepol/man/man3/0040755 0000000 0000000 00000000000 13756670065 013051 5ustar000000000 0000000 libsepol/man/man3/sepol_check_context.30100644 0000000 0000000 00000001541 13756670065 017156 0ustar000000000 0000000 .TH "sepol_check_context" "3" "15 March 2005" "sds@tycho.nsa.gov" "SE Linux binary policy API documentation" .SH "NAME" sepol_check_context \- Check the validity of a security context against a binary policy. .SH "SYNOPSIS" .B #include .sp .BI "int sepol_check_context(const char *" context ");" .sp .BI "int sepol_set_policydb_from_file(FILE *" fp ");" .SH "DESCRIPTION" .B sepol_check_context checks the validity of a security context against a binary policy previously loaded from a file via .B sepol_set_policydb_from_file. It is used by .B setfiles -c to validate a file contexts configuration against the binary policy upon policy builds. For validating a context against the active policy on a SELinux system, use .B security_check_context from libselinux instead. .SH "RETURN VALUE" Returns 0 on success or \-1 with errno set otherwise. libsepol/man/man3/sepol_genbools.30100644 0000000 0000000 00000002455 13756670065 016152 0ustar000000000 0000000 .TH "sepol_genbools" "3" "11 August 2004" "sds@tycho.nsa.gov" "SE Linux binary policy API documentation" .SH "NAME" sepol_genbools \- Rewrite a binary policy with different boolean settings .SH "SYNOPSIS" .B #include .sp .BI "int sepol_genbools(void *" data ", size_t "len ", const char *" boolpath ); .br .BI "int sepol_genbools_array(void *" data ", size_t " len ", char **" names ", int *" values ", int " nel ); .SH "DESCRIPTION" .B sepol_genbools rewrites a binary policy stored in the memory region described by (data, len) to use the boolean settings specified in the file named by boolpath. The boolean settings are specified by name=value lines where value may be 0 or false to disable or 1 or true to enable. The binary policy is rewritten in place in memory. .B sepol_genbools_array does likewise, but obtains the boolean settings from the parallel arrays (names, values) with nel elements each. .SH "RETURN VALUE" Returns 0 on success or \-1 otherwise, with errno set appropriately. An errno of ENOENT indicates that the boolean file did not exist. An errno of EINVAL indicates that one or more booleans listed in the boolean file was undefined in the policy or had an invalid value specified; in this case, the binary policy is still rewritten but any invalid boolean settings are ignored. libsepol/man/man3/sepol_genusers.30100644 0000000 0000000 00000003565 13756670065 016200 0ustar000000000 0000000 .TH "sepol_genusers" "3" "15 March 2005" "sds@tycho.nsa.gov" "SE Linux binary policy API documentation" .SH "NAME" sepol_genusers \- Generate a new binary policy image with a customized user configuration .SH "SYNOPSIS" .B #include .sp .BI "int sepol_genusers(void *" data ", size_t "len ", const char *" usersdir ", void *" newdata ", size_t *" newlen); .sp .BI "void sepol_set_delusers(int " on ");" .SH "DESCRIPTION" .B sepol_genusers generates a new binary policy image from an existing binary policy image stored in the memory region described by the starting address .I data and the length .I len and a pair of user configuration files named .B system.users and .B local.users from the directory specified by .I usersdir. The resulting binary policy is placed into dynamically allocated memory and the variables .I newdata and .I newlen are set to refer to the new binary image's starting address and length. The original binary policy image is not modified. By default, .B sepol_genusers will preserve user entries that are defined in the original binary policy image but not defined in the user configuration files. If such user entries should instead by omitted entirely from the new binary policy image, then the .B sepol_set_delusers function may be called with .I on set to 1 prior to calling .B sepol_genusers in order to enable deletion of such users. .SH "RETURN VALUE" Returns 0 on success or \-1 otherwise, with errno set appropriately. An errno of ENOENT indicates that one or both of the user configuration files did not exist. An errno of EINVAL indicates that either the original binary policy image or the generated one were invalid. An errno of ENOMEM indicates that insufficient memory was available to process the original binary policy image or to generate the new policy image. Invalid entries in the user configuration files are skipped with a warning. libsepol/man/man8/0040755 0000000 0000000 00000000000 13756670065 013056 5ustar000000000 0000000 libsepol/man/man8/chkcon.80100644 0000000 0000000 00000003160 13756670065 014411 0ustar000000000 0000000 .\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 1997 Manoj Srivastava .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual 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 General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" .TH CHKCON 8 "Mar 12 2005" "SELinux" "SELinux Command Line documentation" .SH NAME chkcon \- determine if a security context is valid for a given binary policy .SH SYNOPSIS chkcon policy_file context .SH DESCRIPTION This utility validates (the string representation of) a security context specified by the argument .I context against configuration data read in from a policy database binary representation file specified by the argument .I policy_file. .SH FILES policy file .SH AUTHOR This manual page (and just the manual page) was written by Manoj Srivastava . libsepol/man/man8/genpolbools.80100644 0000000 0000000 00000001034 13756670065 015465 0ustar000000000 0000000 .TH "genpolbools" "8" "11 August 2004" "sds@tycho.nsa.gov" "SELinux Command Line documentation" .SH "NAME" genpolbools \- Rewrite a binary policy with different boolean settings .SH "SYNOPSIS" .B genpolbools oldpolicy booleans newpolicy .SH "DESCRIPTION" .B genpolbools rewrites an existing binary policy with different boolean settings, generating a new binary policy. The booleans file specifies the different boolean settings using name=value lines, where value can be 0 or false to disable the boolean or 1 or true to enable it. libsepol/man/man8/genpolusers.80100644 0000000 0000000 00000003133 13756670065 015512 0ustar000000000 0000000 .\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 1997 Manoj Srivastava .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual 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 General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" .TH GENPOLUSERS 8 "Mar 12 2005" "SELinux" "SELinux Command Line documentation" .SH NAME genpolusers \- Generate new binary policy with updated user configuration .SH SYNOPSIS genpolusers in-policy usersdir out-policy .SH DESCRIPTION Given an existing binary policy file .I in\-policy, generate a new binary policy .I out\-policy with an updated user configuration based on any .B system.users and .B local.users files in the specified .I usersdir. .SH AUTHOR This manual page (and just the manual page) was written by Manoj Srivastava . libsepol/man/ru/0040755 0000000 0000000 00000000000 13756670065 012641 5ustar000000000 0000000 libsepol/man/ru/man8/0040755 0000000 0000000 00000000000 13756670065 013504 5ustar000000000 0000000 libsepol/man/ru/man8/chkcon.80100644 0000000 0000000 00000004173 13756670065 015044 0ustar000000000 0000000 .\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 1997 Manoj Srivastava .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual 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 General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" .TH CHKCON 8 "12 марта 2005" "SELinux" "Документация по командной строке SELinux" .SH ИМЯ chkcon \- определить, является ли контекст безопасности действительным для конкретной двоичной политики .SH ОБЗОР chkcon policy_file context .SH ОПИСАНИЕ Эта утилита проверяет контекст безопасности (его строковое представление), заданный аргументом .I context, относительно данных конфигурации, прочтённых из файла двоичного представления базы данных политик, заданного аргументом .I policy_file. .SH ФАЙЛЫ policy file .SH АВТОРЫ Эта страница руководства (и только она) была написана Manoj Srivastava . Перевод на русский язык выполнила Герасименко Олеся . libsepol/src/0040755 0000000 0000000 00000000000 13756670065 012227 5ustar000000000 0000000 libsepol/src/Makefile0100644 0000000 0000000 00000005121 13756670065 013663 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr INCLUDEDIR ?= $(PREFIX)/include LIBDIR ?= $(PREFIX)/lib SHLIBDIR ?= /lib RANLIB ?= ranlib CILDIR ?= ../cil VERSION = $(shell cat ../VERSION) LIBVERSION = 1 LEX = flex CIL_GENERATED = $(CILDIR)/src/cil_lexer.c LIBA=libsepol.a TARGET=libsepol.so LIBPC=libsepol.pc LIBMAP=libsepol.map LIBSO=$(TARGET).$(LIBVERSION) OBJS= $(patsubst %.c,%.o,$(sort $(wildcard *.c))) LOBJS= $(patsubst %.c,%.lo,$(sort $(wildcard *.c))) CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-format-attribute -O2 override CFLAGS += -I. -I../include -D_GNU_SOURCE ifneq ($(DISABLE_CIL),y) OBJS += $(sort $(patsubst %.c,%.o,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) LOBJS += $(sort $(patsubst %.c,%.lo,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) override CFLAGS += -I$(CILDIR)/include endif LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=$(LIBMAP),-z,defs LN=ln OS := $(shell uname) ifeq ($(OS), Darwin) LD_SONAME_FLAGS=-install_name,$(LIBSO) LDFLAGS += -undefined dynamic_lookup LN=gln endif all: $(LIBA) $(LIBSO) $(LIBPC) $(LIBA): $(OBJS) $(AR) rcs $@ $^ $(RANLIB) $@ $(LIBSO): $(LOBJS) $(LIBMAP) $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(LOBJS) -Wl,$(LD_SONAME_FLAGS) ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBDIR):; s:@includedir@:$(INCLUDEDIR):' < $< > $@ $(LIBMAP): $(LIBMAP).in ifneq ($(DISABLE_CIL),y) cp $< $@ else sed -e '/^\s*cil_/d' < $< > $@ endif ifneq ($(DISABLE_CIL),y) $(CILDIR)/src/cil_lexer.o: $(CILDIR)/src/cil_lexer.c $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -c -o $@ $< $(CILDIR)/src/cil_lexer.lo: $(CILDIR)/src/cil_lexer.c $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< $(CILDIR)/src/cil_lexer.c: $(CILDIR)/src/cil_lexer.l $(LEX) -o $@ $< endif %.o: %.c $(CC) $(CFLAGS) -fPIC -c -o $@ $< %.lo: %.c $(CC) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< install: all test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR) install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR) test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR) install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR) test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig $(LN) -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET) relabel: /sbin/restorecon $(DESTDIR)$(SHLIBDIR)/$(LIBSO) clean: -rm -f $(LIBPC) $(LIBMAP) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(CIL_GENERATED) indent: ../../scripts/Lindent $(wildcard *.[ch]) libsepol/src/assertion.c0100644 0000000 0000000 00000040415 13756670065 014403 0ustar000000000 0000000 /* Authors: Joshua Brindle * * Assertion checker for avtab entries, taken from * checkpolicy.c by Stephen Smalley * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "private.h" #include "debug.h" struct avtab_match_args { sepol_handle_t *handle; policydb_t *p; avrule_t *avrule; avtab_t *avtab; unsigned long errors; }; static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms) { if (avrule->source_filename) { ERR(handle, "neverallow on line %lu of %s (or line %lu of policy.conf) violated by allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], sepol_av_to_string(p, curperm->tclass, perms)); } else if (avrule->line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", avrule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], sepol_av_to_string(p, curperm->tclass, perms)); } else { ERR(handle, "neverallow violated by allow %s %s:%s {%s };", p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], sepol_av_to_string(p, curperm->tclass, perms)); } } static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data) { for (; cp; cp = cp->next) { if ((cp->tclass == class) && (cp->data & data)) { break; } } if (!cp) return 0; return 1; } static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) { size_t i; for (i = 0; i < EXTENDED_PERMS_LEN; i++) { if (perms1[i] & perms2[i]) return 1; } return 0; } static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow) { int rc = 0; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { if (neverallow->driver == allow->driver) rc = extended_permissions_and(neverallow->perms, allow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { rc = xperm_test(neverallow->driver, allow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { rc = xperm_test(allow->driver, neverallow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { rc = extended_permissions_and(neverallow->perms, allow->perms); } return rc; } /* Compute which allowed extended permissions violate the neverallow rule */ static void extended_permissions_violated(avtab_extended_perms_t *result, av_extended_perms_t *neverallow, avtab_extended_perms_t *allow) { size_t i; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = allow->driver; for (i = 0; i < EXTENDED_PERMS_LEN; i++) result->perms[i] = neverallow->perms[i] & allow->perms[i]; } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = neverallow->driver; memcpy(result->perms, neverallow->perms, sizeof(result->perms)); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = allow->driver; memcpy(result->perms, allow->perms, sizeof(result->perms)); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { result->specified = AVTAB_XPERMS_IOCTLDRIVER; for (i = 0; i < EXTENDED_PERMS_LEN; i++) result->perms[i] = neverallow->perms[i] & allow->perms[i]; } } /* Same scenarios of interest as check_assertion_extended_permissions */ static int report_assertion_extended_permissions(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms, avtab_key_t *k, avtab_t *avtab) { avtab_ptr_t node; avtab_key_t tmp_key; avtab_extended_perms_t *xperms; avtab_extended_perms_t error; ebitmap_t *sattr = &p->type_attr_map[stype]; ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; int rc = 1; int ret = 0; memcpy(&tmp_key, k, sizeof(avtab_key_t)); tmp_key.specified = AVTAB_XPERMS_ALLOWED; ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; tmp_key.source_type = i + 1; tmp_key.target_type = j + 1; for (node = avtab_search_node(avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) continue; rc = check_extended_permissions(avrule->xperms, xperms); /* failure on the extended permission check_extended_permissions */ if (rc) { extended_permissions_violated(&error, avrule->xperms, xperms); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" "allowxperm %s %s:%s %s;", avrule->source_line, avrule->source_filename, avrule->line, p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], sepol_extended_perms_to_string(&error)); rc = 0; ret++; } } } } /* failure on the regular permissions */ if (rc) { ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" "allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], sepol_av_to_string(p, curperm->tclass, perms)); ret++; } return ret; } static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args) { int rc = 0; struct avtab_match_args *a = (struct avtab_match_args *)args; sepol_handle_t *handle = a->handle; policydb_t *p = a->p; avtab_t *avtab = a->avtab; avrule_t *avrule = a->avrule; class_perm_node_t *cp; uint32_t perms; ebitmap_t src_matches, tgt_matches, self_matches, matches; ebitmap_node_t *snode, *tnode; unsigned int i, j; if ((k->specified & AVTAB_ALLOWED) == 0) return 0; if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) return 0; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); ebitmap_init(&matches); rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc) goto oom; if (ebitmap_length(&src_matches) == 0) goto exit; rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc) goto oom; if (avrule->flags == RULE_SELF) { rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]); if (rc) goto oom; rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches); if (rc) goto oom; if (ebitmap_length(&self_matches) > 0) { rc = ebitmap_union(&tgt_matches, &self_matches); if (rc) goto oom; } } if (ebitmap_length(&tgt_matches) == 0) goto exit; for (cp = avrule->perms; cp; cp = cp->next) { perms = cp->data & d->data; if ((cp->tclass != k->target_class) || !perms) { continue; } ebitmap_for_each_bit(&src_matches, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(&tgt_matches, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { a->errors += report_assertion_extended_permissions(handle,p, avrule, i, j, cp, perms, k, avtab); } else { a->errors++; report_failure(handle, p, avrule, i, j, cp, perms); } } } } goto exit; oom: ERR(NULL, "Out of memory - unable to check neverallows"); exit: ebitmap_destroy(&src_matches); ebitmap_destroy(&tgt_matches); ebitmap_destroy(&self_matches); ebitmap_destroy(&matches); return rc; } int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule) { int rc; struct avtab_match_args args; args.handle = handle; args.p = p; args.avrule = avrule; args.errors = 0; rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args); if (rc) goto oom; rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args); if (rc) goto oom; return args.errors; oom: return rc; } /* * Look up the extended permissions in avtab and verify that neverallowed * permissions are not granted. */ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab, unsigned int stype, unsigned int ttype, avtab_key_t *k, policydb_t *p) { avtab_ptr_t node; avtab_key_t tmp_key; avtab_extended_perms_t *xperms; av_extended_perms_t *neverallow_xperms = avrule->xperms; ebitmap_t *sattr = &p->type_attr_map[stype]; ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; int rc = 1; memcpy(&tmp_key, k, sizeof(avtab_key_t)); tmp_key.specified = AVTAB_XPERMS_ALLOWED; ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; tmp_key.source_type = i + 1; tmp_key.target_type = j + 1; for (node = avtab_search_node(avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) continue; rc = check_extended_permissions(neverallow_xperms, xperms); if (rc) break; } } } return rc; } /* * When the ioctl permission is granted on an avtab entry that matches an * avrule neverallowxperm entry, enumerate over the matching * source/target/class sets to determine if the extended permissions exist * and if the neverallowed ioctls are granted. * * Four scenarios of interest: * 1. PASS - the ioctl permission is not granted for this source/target/class * This case is handled in check_assertion_avtab_match * 2. PASS - The ioctl permission is granted AND the extended permission * is NOT granted * 3. FAIL - The ioctl permission is granted AND no extended permissions * exist * 4. FAIL - The ioctl permission is granted AND the extended permission is * granted */ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab, avtab_key_t *k, policydb_t *p) { ebitmap_t src_matches, tgt_matches, self_matches, matches; unsigned int i, j; ebitmap_node_t *snode, *tnode; class_perm_node_t *cp; int rc; int ret = 1; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); ebitmap_init(&matches); rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc) goto oom; if (ebitmap_length(&src_matches) == 0) goto exit; rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc) goto oom; if (avrule->flags == RULE_SELF) { rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]); if (rc) goto oom; rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches); if (rc) goto oom; if (ebitmap_length(&self_matches) > 0) { rc = ebitmap_union(&tgt_matches, &self_matches); if (rc) goto oom; } } if (ebitmap_length(&tgt_matches) == 0) goto exit; for (cp = avrule->perms; cp; cp = cp->next) { if (cp->tclass != k->target_class) continue; ebitmap_for_each_bit(&src_matches, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(&tgt_matches, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; ret = check_assertion_extended_permissions_avtab( avrule, avtab, i, j, k, p); if (ret) goto exit; } } } goto exit; oom: ERR(NULL, "Out of memory - unable to check neverallows"); exit: ebitmap_destroy(&src_matches); ebitmap_destroy(&tgt_matches); ebitmap_destroy(&matches); return ret; } static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args) { int rc, rc2 = 0; struct avtab_match_args *a = (struct avtab_match_args *)args; policydb_t *p = a->p; avrule_t *avrule = a->avrule; avtab_t *avtab = a->avtab; if ((k->specified & AVTAB_ALLOWED) == 0) goto exit; if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) goto exit; rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc == 0) goto exit; if (avrule->flags == RULE_SELF) { /* If the neverallow uses SELF, then it is not enough that the * neverallow's source matches the src and tgt of the rule being checked. * It must match the same thing in the src and tgt, so AND the source * and target together and check for a match on the result. */ ebitmap_t match; rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] ); if (rc) { ebitmap_destroy(&match); goto oom; } rc2 = ebitmap_match_any(&avrule->stypes.types, &match); ebitmap_destroy(&match); } /* neverallow may have tgts even if it uses SELF */ rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc == 0 && rc2 == 0) goto exit; if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { rc = check_assertion_extended_permissions(avrule, avtab, k, p); if (rc == 0) goto exit; } return 1; exit: return 0; oom: ERR(NULL, "Out of memory - unable to check neverallows"); return rc; } int check_assertion(policydb_t *p, avrule_t *avrule) { int rc; struct avtab_match_args args; args.handle = NULL; args.p = p; args.avrule = avrule; args.errors = 0; args.avtab = &p->te_avtab; rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args); if (rc == 0) { args.avtab = &p->te_cond_avtab; rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args); } return rc; } int check_assertions(sepol_handle_t * handle, policydb_t * p, avrule_t * avrules) { int rc; avrule_t *a; unsigned long errors = 0; if (!avrules) { /* Since assertions are stored in avrules, if it is NULL there won't be any to check. This also prevents an invalid free if the avtabs are never initialized */ return 0; } for (a = avrules; a != NULL; a = a->next) { if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))) continue; rc = check_assertion(p, a); if (rc) { rc = report_assertion_failures(handle, p, a); if (rc < 0) { ERR(handle, "Error occurred while checking neverallows"); return -1; } errors += rc; } } if (errors) ERR(handle, "%lu neverallow failures occurred", errors); return errors ? -1 : 0; } libsepol/src/av_permissions.h0100644 0000000 0000000 00000000241 13756670065 015433 0ustar000000000 0000000 /* Used by security_compute_av. */ #define PROCESS__TRANSITION 0x00000002UL #define PROCESS__DYNTRANSITION 0x00800000UL libsepol/src/avrule_block.c0100644 0000000 0000000 00000012774 13756670065 015053 0ustar000000000 0000000 /* Authors: Jason Tang * * Functions that manipulate a logical block (conditional, optional, * or global scope) for a policy module. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include /* It is anticipated that there be less declarations within an avrule * block than the global policy. Thus the symbol table sizes are * smaller than those listed in policydb.c */ static unsigned int symtab_sizes[SYM_NUM] = { 2, 4, 8, 32, 16, 4, 2, 2, }; avrule_block_t *avrule_block_create(void) { avrule_block_t *block; if ((block = calloc(1, sizeof(*block))) == NULL) { return NULL; } return block; } avrule_decl_t *avrule_decl_create(uint32_t decl_id) { avrule_decl_t *decl; int i; if ((decl = calloc(1, sizeof(*decl))) == NULL) { return NULL; } decl->decl_id = decl_id; for (i = 0; i < SYM_NUM; i++) { if (symtab_init(&decl->symtab[i], symtab_sizes[i])) { avrule_decl_destroy(decl); return NULL; } } for (i = 0; i < SYM_NUM; i++) { ebitmap_init(&decl->required.scope[i]); ebitmap_init(&decl->declared.scope[i]); } return decl; } /* note that unlike the other destroy functions, this one does /NOT/ * destroy the pointer itself */ static void scope_index_destroy(scope_index_t * scope) { unsigned int i; if (scope == NULL) { return; } for (i = 0; i < SYM_NUM; i++) { ebitmap_destroy(scope->scope + i); } if (scope->class_perms_map) { for (i = 0; i < scope->class_perms_len; i++) { ebitmap_destroy(scope->class_perms_map + i); } } free(scope->class_perms_map); } void avrule_decl_destroy(avrule_decl_t * x) { if (x == NULL) { return; } cond_list_destroy(x->cond_list); avrule_list_destroy(x->avrules); role_trans_rule_list_destroy(x->role_tr_rules); filename_trans_rule_list_destroy(x->filename_trans_rules); role_allow_rule_list_destroy(x->role_allow_rules); range_trans_rule_list_destroy(x->range_tr_rules); scope_index_destroy(&x->required); scope_index_destroy(&x->declared); symtabs_destroy(x->symtab); free(x->module_name); free(x); } void avrule_block_destroy(avrule_block_t * x) { avrule_decl_t *decl; if (x == NULL) { return; } decl = x->branch_list; while (decl != NULL) { avrule_decl_t *next_decl = decl->next; avrule_decl_destroy(decl); decl = next_decl; } free(x); } void avrule_block_list_destroy(avrule_block_t * x) { while (x != NULL) { avrule_block_t *next = x->next; avrule_block_destroy(x); x = next; } } /* Get a conditional node from a avrule_decl with the same expression. * If that expression does not exist then create one. */ cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond) { cond_list_t *result; int was_created; result = cond_node_find(p, cond, decl->cond_list, &was_created); if (result != NULL && was_created) { result->next = decl->cond_list; decl->cond_list = result; } return result; } /* Look up an identifier in a policy's scoping table. If it is there, * marked as SCOPE_DECL, and any of its declaring block has been enabled, * then return 1. Otherwise return 0. Can only be called after the * decl_val_to_struct index has been created */ int is_id_enabled(char *id, policydb_t * p, int symbol_table) { scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); avrule_decl_t *decl; uint32_t len = scope->decl_ids_len; if (scope == NULL) { return 0; } if (scope->scope != SCOPE_DECL) { return 0; } if (len < 1) { return 0; } if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) { uint32_t i; for (i = 0; i < len; i++) { decl = p->decl_val_to_struct[scope->decl_ids[i] - 1]; if (decl != NULL && decl->enabled) { return 1; } } } else { decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1]; if (decl != NULL && decl->enabled) { return 1; } } return 0; } /* Check if a particular permission is present within the given class, * and that the class is enabled. Returns 1 if both conditions are * true, 0 if neither could be found or if the class id disabled. */ int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) { class_datum_t *cladatum; perm_datum_t *perm; if (!is_id_enabled(class_id, p, SYM_CLASSES)) { return 0; } cladatum = (class_datum_t *) hashtab_search(p->p_classes.table, class_id); if (cladatum == NULL) { return 0; } perm = hashtab_search(cladatum->permissions.table, perm_id); if (perm == NULL && cladatum->comdatum != 0) { /* permission was not in this class. before giving * up, check the class's parent */ perm = hashtab_search(cladatum->comdatum->permissions.table, perm_id); } if (perm == NULL) { return 0; } return 1; } libsepol/src/avtab.c0100644 0000000 0000000 00000035670 13756670065 013500 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura * Tuned number of hash slots for avtab to reduce memory usage */ /* Updated: Frank Mayer * and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Code cleanup * * Updated: Karl MacMillan * * Copyright (C) 2003 Tresys Technology, LLC * Copyright (C) 2003,2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the access vector table type. */ #include #include #include #include #include "debug.h" #include "private.h" /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask) { static const uint32_t c1 = 0xcc9e2d51; static const uint32_t c2 = 0x1b873593; static const uint32_t r1 = 15; static const uint32_t r2 = 13; static const uint32_t m = 5; static const uint32_t n = 0xe6546b64; uint32_t hash = 0; #define mix(input) { \ uint32_t v = input; \ v *= c1; \ v = (v << r1) | (v >> (32 - r1)); \ v *= c2; \ hash ^= v; \ hash = (hash << r2) | (hash >> (32 - r2)); \ hash = hash * m + n; \ } mix(keyp->target_class); mix(keyp->target_type); mix(keyp->source_type); #undef mix hash ^= hash >> 16; hash *= 0x85ebca6b; hash ^= hash >> 13; hash *= 0xc2b2ae35; hash ^= hash >> 16; return hash & mask; } static avtab_ptr_t avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key, avtab_datum_t * datum) { avtab_ptr_t newnode; avtab_extended_perms_t *xperms; newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node)); if (newnode == NULL) return NULL; memset(newnode, 0, sizeof(struct avtab_node)); newnode->key = *key; if (key->specified & AVTAB_XPERMS) { xperms = calloc(1, sizeof(avtab_extended_perms_t)); if (xperms == NULL) { free(newnode); return NULL; } if (datum->xperms) /* else caller populates xperms */ *xperms = *(datum->xperms); newnode->datum.xperms = xperms; /* data is usually ignored with xperms, except in the case of * neverallow checking, which requires permission bits to be set. * So copy data so it is set in the avtab */ newnode->datum.data = datum->data; } else { newnode->datum = *datum; } if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } h->nel++; return newnode; } int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum) { int hvalue; avtab_ptr_t prev, cur, newnode; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return SEPOL_ENOMEM; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) { /* Extended permissions are not necessarily unique */ if (specified & AVTAB_XPERMS) break; return SEPOL_EEXIST; } if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } newnode = avtab_insert_node(h, hvalue, prev, key, datum); if (!newnode) return SEPOL_ENOMEM; return 0; } /* Unlike avtab_insert(), this function allow multiple insertions of the same * key/specified mask into the table, as needed by the conditional avtab. * It also returns a pointer to the node inserted. */ avtab_ptr_t avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum) { int hvalue; avtab_ptr_t prev, cur, newnode; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) break; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } newnode = avtab_insert_node(h, hvalue, prev, key, datum); return newnode; } avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * key) { int hvalue; avtab_ptr_t cur; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) return &cur->datum; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } return NULL; } /* This search function returns a node pointer, and can be used in * conjunction with avtab_search_next_node() */ avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key) { int hvalue; avtab_ptr_t cur; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) return cur; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } return NULL; } avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified) { avtab_ptr_t cur; if (!node) return NULL; specified &= ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); for (cur = node->next; cur; cur = cur->next) { if (node->key.source_type == cur->key.source_type && node->key.target_type == cur->key.target_type && node->key.target_class == cur->key.target_class && (specified & cur->key.specified)) return cur; if (node->key.source_type < cur->key.source_type) break; if (node->key.source_type == cur->key.source_type && node->key.target_type < cur->key.target_type) break; if (node->key.source_type == cur->key.source_type && node->key.target_type == cur->key.target_type && node->key.target_class < cur->key.target_class) break; } return NULL; } void avtab_destroy(avtab_t * h) { unsigned int i; avtab_ptr_t cur, temp; if (!h || !h->htable) return; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; while (cur != NULL) { if (cur->key.specified & AVTAB_XPERMS) { free(cur->datum.xperms); } temp = cur; cur = cur->next; free(temp); } h->htable[i] = NULL; } free(h->htable); h->htable = NULL; h->nslot = 0; h->mask = 0; } int avtab_map(avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args) { unsigned int i; int ret; avtab_ptr_t cur; if (!h) return 0; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; while (cur != NULL) { ret = apply(&cur->key, &cur->datum, args); if (ret) return ret; cur = cur->next; } } return 0; } int avtab_init(avtab_t * h) { h->htable = NULL; h->nel = 0; return 0; } int avtab_alloc(avtab_t *h, uint32_t nrules) { uint32_t mask = 0; uint32_t shift = 0; uint32_t work = nrules; uint32_t nslot = 0; if (nrules == 0) goto out; while (work) { work = work >> 1; shift++; } if (shift > 2) shift = shift - 2; nslot = 1 << shift; if (nslot > MAX_AVTAB_HASH_BUCKETS) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; h->htable = calloc(nslot, sizeof(avtab_ptr_t)); if (!h->htable) return -1; out: h->nel = 0; h->nslot = nslot; h->mask = mask; return 0; } void avtab_hash_eval(avtab_t * h, char *tag) { unsigned int i, chain_len, slots_used, max_chain_len; avtab_ptr_t cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, h->nslot, max_chain_len); } /* Ordering of datums in the original avtab format in the policy file. */ static uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, AVTAB_AUDITALLOW, AVTAB_TRANSITION, AVTAB_CHANGE, AVTAB_MEMBER, AVTAB_XPERMS_ALLOWED, AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_DONTAUDIT }; int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, int (*insertf) (avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p), void *p) { uint8_t buf8; uint16_t buf16[4], enabled; uint32_t buf32[8], items, items2, val; avtab_key_t key; avtab_datum_t datum; avtab_extended_perms_t xperms; unsigned set; unsigned int i; int rc; memset(&key, 0, sizeof(avtab_key_t)); memset(&datum, 0, sizeof(avtab_datum_t)); memset(&xperms, 0, sizeof(avtab_extended_perms_t)); if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items2 = le32_to_cpu(buf32[0]); if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) { ERR(fp->handle, "invalid item count"); return -1; } rc = next_entry(buf32, fp, sizeof(uint32_t) * items2); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; val = le32_to_cpu(buf32[items++]); key.source_type = (uint16_t) val; if (key.source_type != val) { ERR(fp->handle, "truncated source type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_type = (uint16_t) val; if (key.target_type != val) { ERR(fp->handle, "truncated target type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_class = (uint16_t) val; if (key.target_class != val) { ERR(fp->handle, "truncated target class"); return -1; } val = le32_to_cpu(buf32[items++]); enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { ERR(fp->handle, "null entry"); return -1; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { ERR(fp->handle, "entry has both access " "vectors and types"); return -1; } for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (val & spec_order[i]) { key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); rc = insertf(a, &key, &datum, p); if (rc) return rc; } } if (items != items2) { ERR(fp->handle, "entry only had %d items, " "expected %d", items2, items); return -1; } return 0; } rc = next_entry(buf16, fp, sizeof(uint16_t) * 4); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; key.source_type = le16_to_cpu(buf16[items++]); key.target_type = le16_to_cpu(buf16[items++]); key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); set = 0; for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (key.specified & spec_order[i]) set++; } if (!set || set > 1) { ERR(fp->handle, "more than one specifier"); return -1; } if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && (key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "policy version %u does not support extended " "permissions rules and one was specified\n", vers); return -1; } else if (key.specified & AVTAB_XPERMS) { rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.specified = buf8; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.driver = buf8; rc = next_entry(buf32, fp, sizeof(uint32_t)*8); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } for (i = 0; i < ARRAY_SIZE(xperms.perms); i++) xperms.perms[i] = le32_to_cpu(buf32[i]); datum.xperms = &xperms; } else { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } datum.data = le32_to_cpu(*buf32); } return insertf(a, &key, &datum, p); } static int avtab_insertf(avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p __attribute__ ((unused))) { return avtab_insert(a, k, d); } int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) { unsigned int i; int rc; uint32_t buf[1]; uint32_t nel; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated table"); goto bad; } nel = le32_to_cpu(buf[0]); if (!nel) { ERR(fp->handle, "table is empty"); goto bad; } rc = avtab_alloc(a, nel); if (rc) { ERR(fp->handle, "out of memory"); goto bad; } for (i = 0; i < nel; i++) { rc = avtab_read_item(fp, vers, a, avtab_insertf, NULL); if (rc) { if (rc == SEPOL_ENOMEM) ERR(fp->handle, "out of memory"); if (rc == SEPOL_EEXIST) ERR(fp->handle, "duplicate entry"); ERR(fp->handle, "failed on entry %d of %u", i, nel); goto bad; } } return 0; bad: avtab_destroy(a); return -1; } libsepol/src/boolean_internal.h0100644 0000000 0000000 00000000712 13756670065 015710 0ustar000000000 0000000 #ifndef _SEPOL_BOOLEAN_INTERNAL_H_ #define _SEPOL_BOOLEAN_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_bool_key_create) hidden_proto(sepol_bool_key_unpack) hidden_proto(sepol_bool_get_name) hidden_proto(sepol_bool_set_name) hidden_proto(sepol_bool_get_value) hidden_proto(sepol_bool_set_value) hidden_proto(sepol_bool_create) hidden_proto(sepol_bool_free) #endif libsepol/src/boolean_record.c0100644 0000000 0000000 00000006601 13756670065 015350 0ustar000000000 0000000 #include #include #include #include "boolean_internal.h" #include "debug.h" struct sepol_bool { /* This boolean's name */ char *name; /* Its value */ int value; }; struct sepol_bool_key { /* This boolean's name */ char *name; }; int sepol_bool_key_create(sepol_handle_t * handle, const char *name, sepol_bool_key_t ** key_ptr) { sepol_bool_key_t *tmp_key = (sepol_bool_key_t *) malloc(sizeof(struct sepol_bool_key)); if (!tmp_key) { ERR(handle, "out of memory, " "could not create boolean key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, " "could not create boolean key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(sepol_bool_key_create) void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name) { *name = key->name; } hidden_def(sepol_bool_key_unpack) int sepol_bool_key_extract(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_key_t ** key_ptr) { if (sepol_bool_key_create(handle, boolean->name, key_ptr) < 0) { ERR(handle, "could not extract key from boolean %s", boolean->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_bool_key_free(sepol_bool_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_bool_compare(const sepol_bool_t * boolean, const sepol_bool_key_t * key) { return strcmp(boolean->name, key->name); } int sepol_bool_compare2(const sepol_bool_t * boolean, const sepol_bool_t * boolean2) { return strcmp(boolean->name, boolean2->name); } /* Name */ const char *sepol_bool_get_name(const sepol_bool_t * boolean) { return boolean->name; } hidden_def(sepol_bool_get_name) int sepol_bool_set_name(sepol_handle_t * handle, sepol_bool_t * boolean, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set boolean name"); return STATUS_ERR; } free(boolean->name); boolean->name = tmp_name; return STATUS_SUCCESS; } hidden_def(sepol_bool_set_name) /* Value */ int sepol_bool_get_value(const sepol_bool_t * boolean) { return boolean->value; } hidden_def(sepol_bool_get_value) void sepol_bool_set_value(sepol_bool_t * boolean, int value) { boolean->value = value; } hidden_def(sepol_bool_set_value) /* Create */ int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr) { sepol_bool_t *boolean = (sepol_bool_t *) malloc(sizeof(sepol_bool_t)); if (!boolean) { ERR(handle, "out of memory, " "could not create boolean record"); return STATUS_ERR; } boolean->name = NULL; boolean->value = 0; *bool_ptr = boolean; return STATUS_SUCCESS; } hidden_def(sepol_bool_create) /* Deep copy clone */ int sepol_bool_clone(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_t ** bool_ptr) { sepol_bool_t *new_bool = NULL; if (sepol_bool_create(handle, &new_bool) < 0) goto err; if (sepol_bool_set_name(handle, new_bool, boolean->name) < 0) goto err; new_bool->value = boolean->value; *bool_ptr = new_bool; return STATUS_SUCCESS; err: ERR(handle, "could not clone boolean record"); sepol_bool_free(new_bool); return STATUS_ERR; } /* Destroy */ void sepol_bool_free(sepol_bool_t * boolean) { if (!boolean) return; free(boolean->name); free(boolean); } hidden_def(sepol_bool_free) libsepol/src/booleans.c0100644 0000000 0000000 00000010701 13756670065 014171 0ustar000000000 0000000 #include #include #include "handle.h" #include "private.h" #include "debug.h" #include #include #include #include #include "boolean_internal.h" static int bool_update(sepol_handle_t * handle, policydb_t * policydb, const sepol_bool_key_t * key, const sepol_bool_t * data) { const char *cname; char *name; int value; sepol_bool_key_unpack(key, &cname); name = strdup(cname); value = sepol_bool_get_value(data); if (!name) goto omem; cond_bool_datum_t *datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(handle, "boolean %s no longer in policy", name); goto err; } if (value != 0 && value != 1) { ERR(handle, "illegal value %d for boolean %s", value, name); goto err; } free(name); datum->state = value; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(name); ERR(handle, "could not update boolean %s", cname); return STATUS_ERR; } static int bool_to_record(sepol_handle_t * handle, const policydb_t * policydb, int bool_idx, sepol_bool_t ** record) { const char *name = policydb->p_bool_val_to_name[bool_idx]; cond_bool_datum_t *booldatum = policydb->bool_val_to_struct[bool_idx]; int value = booldatum->state; sepol_bool_t *tmp_record = NULL; if (sepol_bool_create(handle, &tmp_record) < 0) goto err; if (sepol_bool_set_name(handle, tmp_record, name) < 0) goto err; sepol_bool_set_value(tmp_record, value); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert boolean %s to record", name); sepol_bool_free(tmp_record); return STATUS_ERR; } int sepol_bool_set(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_bool_key_t * key, const sepol_bool_t * data) { const char *name; sepol_bool_key_unpack(key, &name); policydb_t *policydb = &p->p; if (bool_update(handle, policydb, key, data) < 0) goto err; if (evaluate_conds(policydb) < 0) { ERR(handle, "error while re-evaluating conditionals"); goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not set boolean %s", name); return STATUS_ERR; } int sepol_bool_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { const policydb_t *policydb = &p->p; *response = policydb->p_bools.nprim; return STATUS_SUCCESS; } int sepol_bool_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, int *response) { const policydb_t *policydb = &p->p; const char *cname; char *name = NULL; sepol_bool_key_unpack(key, &cname); name = strdup(cname); if (!name) { ERR(handle, "out of memory, could not check " "if user %s exists", cname); return STATUS_ERR; } *response = (hashtab_search(policydb->p_bools.table, name) != NULL); free(name); return STATUS_SUCCESS; } int sepol_bool_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, sepol_bool_t ** response) { const policydb_t *policydb = &p->p; cond_bool_datum_t *booldatum = NULL; const char *cname; char *name = NULL; sepol_bool_key_unpack(key, &cname); name = strdup(cname); if (!name) goto omem; booldatum = hashtab_search(policydb->p_bools.table, name); if (!booldatum) { *response = NULL; free(name); return STATUS_SUCCESS; } if (bool_to_record(handle, policydb, booldatum->s.value - 1, response) < 0) goto err; free(name); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not query boolean %s", cname); free(name); return STATUS_ERR; } int sepol_bool_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_bool_t * boolean, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; unsigned int nbools = policydb->p_bools.nprim; sepol_bool_t *boolean = NULL; unsigned int i; /* For each boolean */ for (i = 0; i < nbools; i++) { int status; if (bool_to_record(handle, policydb, i, &boolean) < 0) goto err; /* Invoke handler */ status = fn(boolean, arg); if (status < 0) goto err; sepol_bool_free(boolean); boolean = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over booleans"); sepol_bool_free(boolean); return STATUS_ERR; } libsepol/src/conditional.c0100644 0000000 0000000 00000050632 13756670065 014701 0ustar000000000 0000000 /* Authors: Karl MacMillan * Frank Mayer * David Caplan * * Copyright (C) 2003 - 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "private.h" /* move all type rules to top of t/f lists to help kernel on evaluation */ static void cond_optimize(cond_av_list_t ** l) { cond_av_list_t *top, *p, *cur; top = p = cur = *l; while (cur) { if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) { p->next = cur->next; cur->next = top; top = cur; cur = p->next; } else { p = cur; cur = cur->next; } } *l = top; } /* reorder t/f lists for kernel */ void cond_optimize_lists(cond_list_t * cl) { cond_list_t *n; for (n = cl; n != NULL; n = n->next) { cond_optimize(&n->true_list); cond_optimize(&n->false_list); } } static int bool_present(unsigned int target, unsigned int bools[], unsigned int num_bools) { unsigned int i = 0; int ret = 1; if (num_bools > COND_MAX_BOOLS) { return 0; } while (i < num_bools && target != bools[i]) i++; if (i == num_bools) ret = 0; /* got to end w/o match */ return ret; } static int same_bools(cond_node_t * a, cond_node_t * b) { unsigned int i, x; x = a->nbools; /* same number of bools? */ if (x != b->nbools) return 0; /* make sure all the bools in a are also in b */ for (i = 0; i < x; i++) if (!bool_present(a->bool_ids[i], b->bool_ids, x)) return 0; return 1; } /* * Determine if two conditional expressions are equal. */ int cond_expr_equal(cond_node_t * a, cond_node_t * b) { cond_expr_t *cur_a, *cur_b; if (a == NULL || b == NULL) return 0; if (a->nbools != b->nbools) return 0; /* if exprs have <= COND_MAX_BOOLS we can check the precompute values * for the expressions. */ if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) { if (!same_bools(a, b)) return 0; return (a->expr_pre_comp == b->expr_pre_comp); } /* for long expressions we check for exactly the same expression */ cur_a = a->expr; cur_b = b->expr; while (1) { if (cur_a == NULL && cur_b == NULL) return 1; else if (cur_a == NULL || cur_b == NULL) return 0; if (cur_a->expr_type != cur_b->expr_type) return 0; if (cur_a->expr_type == COND_BOOL) { if (cur_a->bool != cur_b->bool) return 0; } cur_a = cur_a->next; cur_b = cur_b->next; } return 1; } /* Create a new conditional node, optionally copying * the conditional expression from an existing node. * If node is NULL then a new node will be created * with no conditional expression. */ cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node) { cond_node_t *new_node; unsigned int i; new_node = (cond_node_t *)malloc(sizeof(cond_node_t)); if (!new_node) { return NULL; } memset(new_node, 0, sizeof(cond_node_t)); if (node) { new_node->expr = cond_copy_expr(node->expr); if (!new_node->expr) { free(new_node); return NULL; } new_node->cur_state = cond_evaluate_expr(p, new_node->expr); new_node->nbools = node->nbools; for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++) new_node->bool_ids[i] = node->bool_ids[i]; new_node->expr_pre_comp = node->expr_pre_comp; new_node->flags = node->flags; } return new_node; } /* Find a conditional (the needle) within a list of existing ones (the * haystack) that has a matching expression. If found, return a * pointer to the existing node, setting 'was_created' to 0. * Otherwise create a new one and return it, setting 'was_created' to * 1. */ cond_node_t *cond_node_find(policydb_t * p, cond_node_t * needle, cond_node_t * haystack, int *was_created) { while (haystack) { if (cond_expr_equal(needle, haystack)) { *was_created = 0; return haystack; } haystack = haystack->next; } *was_created = 1; return cond_node_create(p, needle); } /* return either a pre-existing matching node or create a new node */ cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, cond_node_t * cn) { int was_created; cond_node_t *result = cond_node_find(p, cn, list, &was_created); if (result != NULL && was_created) { /* add conditional node to policy list */ result->next = p->cond_list; p->cond_list = result; } return result; } /* * cond_evaluate_expr evaluates a conditional expr * in reverse polish notation. It returns true (1), false (0), * or undefined (-1). Undefined occurs when the expression * exceeds the stack depth of COND_EXPR_MAXDEPTH. */ int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr) { cond_expr_t *cur; int s[COND_EXPR_MAXDEPTH]; int sp = -1; s[0] = -1; for (cur = expr; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: if (sp == (COND_EXPR_MAXDEPTH - 1)) return -1; sp++; s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; break; case COND_NOT: if (sp < 0) return -1; s[sp] = !s[sp]; break; case COND_OR: if (sp < 1) return -1; sp--; s[sp] |= s[sp + 1]; break; case COND_AND: if (sp < 1) return -1; sp--; s[sp] &= s[sp + 1]; break; case COND_XOR: if (sp < 1) return -1; sp--; s[sp] ^= s[sp + 1]; break; case COND_EQ: if (sp < 1) return -1; sp--; s[sp] = (s[sp] == s[sp + 1]); break; case COND_NEQ: if (sp < 1) return -1; sp--; s[sp] = (s[sp] != s[sp + 1]); break; default: return -1; } } return s[0]; } cond_expr_t *cond_copy_expr(cond_expr_t * expr) { cond_expr_t *cur, *head, *tail, *new_expr; tail = head = NULL; cur = expr; while (cur) { new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t)); if (!new_expr) goto free_head; memset(new_expr, 0, sizeof(cond_expr_t)); new_expr->expr_type = cur->expr_type; new_expr->bool = cur->bool; if (!head) head = new_expr; if (tail) tail->next = new_expr; tail = new_expr; cur = cur->next; } return head; free_head: while (head) { tail = head->next; free(head); head = tail; } return NULL; } /* * evaluate_cond_node evaluates the conditional stored in * a cond_node_t and if the result is different than the * current state of the node it sets the rules in the true/false * list appropriately. If the result of the expression is undefined * all of the rules are disabled for safety. */ static int evaluate_cond_node(policydb_t * p, cond_node_t * node) { int new_state; cond_av_list_t *cur; new_state = cond_evaluate_expr(p, node->expr); if (new_state != node->cur_state) { node->cur_state = new_state; if (new_state == -1) printf ("expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ for (cur = node->true_list; cur != NULL; cur = cur->next) { if (new_state <= 0) { cur->node->key.specified &= ~AVTAB_ENABLED; } else { cur->node->key.specified |= AVTAB_ENABLED; } } for (cur = node->false_list; cur != NULL; cur = cur->next) { /* -1 or 1 */ if (new_state) { cur->node->key.specified &= ~AVTAB_ENABLED; } else { cur->node->key.specified |= AVTAB_ENABLED; } } } return 0; } /* precompute and simplify an expression if possible. If left with !expression, change * to expression and switch t and f. precompute expression for expressions with limited * number of bools. */ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) { cond_expr_t *ne, *e; cond_av_list_t *tmp; unsigned int i, j, orig_value[COND_MAX_BOOLS]; int k; uint32_t test = 0x0; avrule_t *tmp2; cn->nbools = 0; memset(cn->bool_ids, 0, sizeof(cn->bool_ids)); cn->expr_pre_comp = 0x0; /* take care of !expr case */ ne = NULL; e = cn->expr; /* becuase it's RPN look at last element */ while (e->next != NULL) { ne = e; e = e->next; } if (e->expr_type == COND_NOT) { if (ne) { ne->next = NULL; } else { /* ne should never be NULL */ printf ("Found expr with no bools and only a ! - this should never happen.\n"); return -1; } /* swap the true and false lists */ tmp = cn->true_list; cn->true_list = cn->false_list; cn->false_list = tmp; tmp2 = cn->avtrue_list; cn->avtrue_list = cn->avfalse_list; cn->avfalse_list = tmp2; /* free the "not" node in the list */ free(e); } /* find all the bools in the expression */ for (e = cn->expr; e != NULL; e = e->next) { switch (e->expr_type) { case COND_BOOL: i = 0; /* see if we've already seen this bool */ if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) { /* count em all but only record up to COND_MAX_BOOLS */ if (cn->nbools < COND_MAX_BOOLS) cn->bool_ids[cn->nbools++] = e->bool; else cn->nbools++; } break; default: break; } } /* only precompute for exprs with <= COND_AX_BOOLS */ if (cn->nbools <= COND_MAX_BOOLS) { /* save the default values for the bools so we can play with them */ for (i = 0; i < cn->nbools; i++) { orig_value[i] = p->bool_val_to_struct[cn->bool_ids[i] - 1]->state; } /* loop through all possible combinations of values for bools in expression */ for (test = 0x0; test < (0x1U << cn->nbools); test++) { /* temporarily set the value for all the bools in the * expression using the corr. bit in test */ for (j = 0; j < cn->nbools; j++) { p->bool_val_to_struct[cn->bool_ids[j] - 1]->state = (test & (0x1 << j)) ? 1 : 0; } k = cond_evaluate_expr(p, cn->expr); if (k == -1) { printf ("While testing expression, expression result " "was undefined - this should never happen.\n"); return -1; } /* set the bit if expression evaluates true */ if (k) cn->expr_pre_comp |= 0x1 << test; } /* restore bool default values */ for (i = 0; i < cn->nbools; i++) p->bool_val_to_struct[cn->bool_ids[i] - 1]->state = orig_value[i]; } return 0; } int evaluate_conds(policydb_t * p) { int ret; cond_node_t *cur; for (cur = p->cond_list; cur != NULL; cur = cur->next) { ret = evaluate_cond_node(p, cur); if (ret) return ret; } return 0; } int cond_policydb_init(policydb_t * p) { p->bool_val_to_struct = NULL; p->cond_list = NULL; if (avtab_init(&p->te_cond_avtab)) return -1; return 0; } void cond_av_list_destroy(cond_av_list_t * list) { cond_av_list_t *cur, *next; for (cur = list; cur != NULL; cur = next) { next = cur->next; /* the avtab_ptr_t node is destroy by the avtab */ free(cur); } } void cond_expr_destroy(cond_expr_t * expr) { cond_expr_t *cur_expr, *next_expr; if (!expr) return; for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) { next_expr = cur_expr->next; free(cur_expr); } } void cond_node_destroy(cond_node_t * node) { if (!node) return; cond_expr_destroy(node->expr); avrule_list_destroy(node->avtrue_list); avrule_list_destroy(node->avfalse_list); cond_av_list_destroy(node->true_list); cond_av_list_destroy(node->false_list); } void cond_list_destroy(cond_list_t * list) { cond_node_t *next, *cur; if (list == NULL) return; for (cur = list; cur != NULL; cur = next) { next = cur->next; cond_node_destroy(cur); free(cur); } } void cond_policydb_destroy(policydb_t * p) { if (p->bool_val_to_struct != NULL) free(p->bool_val_to_struct); avtab_destroy(&p->te_cond_avtab); cond_list_destroy(p->cond_list); } int cond_init_bool_indexes(policydb_t * p) { if (p->bool_val_to_struct) free(p->bool_val_to_struct); p->bool_val_to_struct = (cond_bool_datum_t **) malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *)); if (!p->bool_val_to_struct) return -1; return 0; } int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); free(datum); return 0; } int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; cond_bool_datum_t *booldatum; booldatum = datum; p = datap; if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim) return -EINVAL; if (p->p_bool_val_to_name[booldatum->s.value - 1] != NULL) return -EINVAL; p->p_bool_val_to_name[booldatum->s.value - 1] = key; p->bool_val_to_struct[booldatum->s.value - 1] = booldatum; return 0; } static int bool_isvalid(cond_bool_datum_t * b) { if (!(b->state == 0 || b->state == 1)) return 0; return 1; } int cond_read_bool(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; cond_bool_datum_t *booldatum; uint32_t buf[3], len; int rc; booldatum = malloc(sizeof(cond_bool_datum_t)); if (!booldatum) return -1; memset(booldatum, 0, sizeof(cond_bool_datum_t)); rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto err; booldatum->s.value = le32_to_cpu(buf[0]); booldatum->state = le32_to_cpu(buf[1]); if (!bool_isvalid(booldatum)) goto err; len = le32_to_cpu(buf[2]); if (str_read(&key, fp, len)) goto err; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; booldatum->flags = le32_to_cpu(buf[0]); } if (hashtab_insert(h, key, booldatum)) goto err; return 0; err: cond_destroy_bool(key, booldatum, 0); return -1; } struct cond_insertf_data { struct policydb *p; cond_av_list_t *other; cond_av_list_t *head; cond_av_list_t *tail; }; static int cond_insertf(avtab_t * a __attribute__ ((unused)), avtab_key_t * k, avtab_datum_t * d, void *ptr) { struct cond_insertf_data *data = ptr; struct policydb *p = data->p; cond_av_list_t *other = data->other, *list, *cur; avtab_ptr_t node_ptr; uint8_t found; /* * For type rules we have to make certain there aren't any * conflicting rules by searching the te_avtab and the * cond_te_avtab. */ if (k->specified & AVTAB_TYPE) { if (avtab_search(&p->te_avtab, k)) { printf ("security: type rule already exists outside of a conditional."); goto err; } /* * If we are reading the false list other will be a pointer to * the true list. We can have duplicate entries if there is only * 1 other entry and it is in our true list. * * If we are reading the true list (other == NULL) there shouldn't * be any other entries. */ if (other) { node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { if (avtab_search_node_next (node_ptr, k->specified)) { printf ("security: too many conflicting type rules."); goto err; } found = 0; for (cur = other; cur != NULL; cur = cur->next) { if (cur->node == node_ptr) { found = 1; break; } } if (!found) { printf ("security: conflicting type rules.\n"); goto err; } } } else { if (avtab_search(&p->te_cond_avtab, k)) { printf ("security: conflicting type rules when adding type rule for true.\n"); goto err; } } } node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); if (!node_ptr) { printf("security: could not insert rule."); goto err; } node_ptr->parse_context = (void *)1; list = malloc(sizeof(cond_av_list_t)); if (!list) goto err; memset(list, 0, sizeof(cond_av_list_t)); list->node = node_ptr; if (!data->head) data->head = list; else data->tail->next = list; data->tail = list; return 0; err: cond_av_list_destroy(data->head); data->head = NULL; return -1; } static int cond_read_av_list(policydb_t * p, void *fp, cond_av_list_t ** ret_list, cond_av_list_t * other) { unsigned int i; int rc; uint32_t buf[1], len; struct cond_insertf_data data; *ret_list = NULL; len = 0; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (len == 0) { return 0; } data.p = p; data.other = other; data.head = NULL; data.tail = NULL; for (i = 0; i < len; i++) { rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); if (rc) return rc; } *ret_list = data.head; return 0; } static int expr_isvalid(policydb_t * p, cond_expr_t * expr) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { printf ("security: conditional expressions uses unknown operator.\n"); return 0; } if (expr->bool > p->p_bools.nprim) { printf ("security: conditional expressions uses unknown bool.\n"); return 0; } return 1; } static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) { uint32_t buf[2]; int len, i, rc; cond_expr_t *expr = NULL, *last = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; node->cur_state = le32_to_cpu(buf[0]); len = 0; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; /* expr */ len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto err; expr = malloc(sizeof(cond_expr_t)); if (!expr) { goto err; } memset(expr, 0, sizeof(cond_expr_t)); expr->expr_type = le32_to_cpu(buf[0]); expr->bool = le32_to_cpu(buf[1]); if (!expr_isvalid(p, expr)) { free(expr); goto err; } if (i == 0) { node->expr = expr; } else { last->next = expr; } last = expr; } if (p->policy_type == POLICY_KERN) { if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) goto err; if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) goto err; } else { if (avrule_read_list(p, &node->avtrue_list, fp)) goto err; if (avrule_read_list(p, &node->avfalse_list, fp)) goto err; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; node->flags = le32_to_cpu(buf[0]); } return 0; err: cond_node_destroy(node); free(node); return -1; } int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) { cond_node_t *node, *last = NULL; uint32_t buf[1]; int i, len, rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel); if (rc) goto err; for (i = 0; i < len; i++) { node = malloc(sizeof(cond_node_t)); if (!node) goto err; memset(node, 0, sizeof(cond_node_t)); if (cond_read_node(p, node, fp) != 0) goto err; if (i == 0) { *list = node; } else { last->next = node; } last = node; } return 0; err: return -1; } /* Determine whether additional permissions are granted by the conditional * av table, and if so, add them to the result */ void cond_compute_av(avtab_t * ctab, avtab_key_t * key, struct sepol_av_decision *avd) { avtab_ptr_t node; if (!ctab || !key || !avd) return; for (node = avtab_search_node(ctab, key); node != NULL; node = avtab_search_node_next(node, key->specified)) { if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) == (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) avd->allowed |= node->datum.data; if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) == (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) /* Since a '0' in an auditdeny mask represents a * permission we do NOT want to audit (dontaudit), we use * the '&' operand to ensure that all '0's in the mask * are retained (much unlike the allow and auditallow cases). */ avd->auditdeny &= node->datum.data; if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) == (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) avd->auditallow |= node->datum.data; } return; } avtab_datum_t *cond_av_list_search(avtab_key_t * key, cond_av_list_t * cond_list) { cond_av_list_t *cur_av; for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { if (cur_av->node->key.source_type == key->source_type && cur_av->node->key.target_type == key->target_type && cur_av->node->key.target_class == key->target_class) return &cur_av->node->datum; } return NULL; } libsepol/src/constraint.c0100644 0000000 0000000 00000002713 13756670065 014557 0ustar000000000 0000000 /* Authors: Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include int constraint_expr_init(constraint_expr_t * expr) { memset(expr, 0, sizeof(*expr)); ebitmap_init(&expr->names); if ((expr->type_names = malloc(sizeof(*expr->type_names))) == NULL) { return -1; } type_set_init(expr->type_names); return 0; } void constraint_expr_destroy(constraint_expr_t * expr) { if (expr != NULL) { ebitmap_destroy(&expr->names); type_set_destroy(expr->type_names); free(expr->type_names); free(expr); } } libsepol/src/context.c0100644 0000000 0000000 00000020156 13756670065 014060 0ustar000000000 0000000 #include #include #include #include #include #include "context_internal.h" #include "debug.h" #include "context.h" #include "handle.h" #include "mls.h" #include "private.h" /* ----- Compatibility ---- */ int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c) { return context_is_valid(p, c); } int sepol_check_context(const char *context) { return sepol_context_to_sid((const sepol_security_context_t)context, strlen(context) + 1, NULL); } /* ---- End compatibility --- */ /* * Return 1 if the fields in the security context * structure `c' are valid. Return 0 otherwise. */ int context_is_valid(const policydb_t * p, const context_struct_t * c) { role_datum_t *role; user_datum_t *usrdatum; ebitmap_t types, roles; int ret = 1; ebitmap_init(&types); ebitmap_init(&roles); if (!c->role || c->role > p->p_roles.nprim) return 0; if (!c->user || c->user > p->p_users.nprim) return 0; if (!c->type || c->type > p->p_types.nprim) return 0; if (c->role != OBJECT_R_VAL) { /* * Role must be authorized for the type. */ role = p->role_val_to_struct[c->role - 1]; if (!role || !ebitmap_get_bit(&role->cache, c->type - 1)) /* role may not be associated with type */ return 0; /* * User must be authorized for the role. */ usrdatum = p->user_val_to_struct[c->user - 1]; if (!usrdatum) return 0; if (!ebitmap_get_bit(&usrdatum->cache, c->role - 1)) /* user may not be associated with role */ return 0; } if (!mls_context_isvalid(p, c)) return 0; return ret; } /* * Write the security context string representation of * the context structure `context' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ int context_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, char **result, size_t * result_len) { char *scontext = NULL; size_t scontext_len = 0; char *ptr; /* Compute the size of the context. */ scontext_len += strlen(policydb->p_user_val_to_name[context->user - 1]) + 1; scontext_len += strlen(policydb->p_role_val_to_name[context->role - 1]) + 1; scontext_len += strlen(policydb->p_type_val_to_name[context->type - 1]); scontext_len += mls_compute_context_len(policydb, context); /* We must null terminate the string */ scontext_len += 1; /* Allocate space for the context; caller must free this space. */ scontext = malloc(scontext_len); if (!scontext) goto omem; scontext[scontext_len - 1] = '\0'; /* * Copy the user name, role name and type name into the context. */ ptr = scontext; sprintf(ptr, "%s:%s:%s", policydb->p_user_val_to_name[context->user - 1], policydb->p_role_val_to_name[context->role - 1], policydb->p_type_val_to_name[context->type - 1]); ptr += strlen(policydb->p_user_val_to_name[context->user - 1]) + 1 + strlen(policydb->p_role_val_to_name[context->role - 1]) + 1 + strlen(policydb->p_type_val_to_name[context->type - 1]); mls_sid_to_context(policydb, context, &ptr); *result = scontext; *result_len = scontext_len; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not convert " "context to string"); free(scontext); return STATUS_ERR; } /* * Create a context structure from the given record */ int context_from_record(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const sepol_context_t * record) { context_struct_t *scontext = NULL; user_datum_t *usrdatum; role_datum_t *roldatum; type_datum_t *typdatum; /* Hashtab keys are not constant - suppress warnings */ char *user = strdup(sepol_context_get_user(record)); char *role = strdup(sepol_context_get_role(record)); char *type = strdup(sepol_context_get_type(record)); const char *mls = sepol_context_get_mls(record); scontext = (context_struct_t *) malloc(sizeof(context_struct_t)); if (!user || !role || !type || !scontext) { ERR(handle, "out of memory"); goto err; } context_init(scontext); /* User */ usrdatum = (user_datum_t *) hashtab_search(policydb->p_users.table, (hashtab_key_t) user); if (!usrdatum) { ERR(handle, "user %s is not defined", user); goto err_destroy; } scontext->user = usrdatum->s.value; /* Role */ roldatum = (role_datum_t *) hashtab_search(policydb->p_roles.table, (hashtab_key_t) role); if (!roldatum) { ERR(handle, "role %s is not defined", role); goto err_destroy; } scontext->role = roldatum->s.value; /* Type */ typdatum = (type_datum_t *) hashtab_search(policydb->p_types.table, (hashtab_key_t) type); if (!typdatum || typdatum->flavor == TYPE_ATTRIB) { ERR(handle, "type %s is not defined", type); goto err_destroy; } scontext->type = typdatum->s.value; /* MLS */ if (mls && !policydb->mls) { ERR(handle, "MLS is disabled, but MLS context \"%s\" found", mls); goto err_destroy; } else if (!mls && policydb->mls) { ERR(handle, "MLS is enabled, but no MLS context found"); goto err_destroy; } if (mls && (mls_from_string(handle, policydb, mls, scontext) < 0)) goto err_destroy; /* Validity check */ if (!context_is_valid(policydb, scontext)) { if (mls) { ERR(handle, "invalid security context: \"%s:%s:%s:%s\"", user, role, type, mls); } else { ERR(handle, "invalid security context: \"%s:%s:%s\"", user, role, type); } goto err_destroy; } *cptr = scontext; free(user); free(type); free(role); return STATUS_SUCCESS; err_destroy: errno = EINVAL; context_destroy(scontext); err: free(scontext); free(user); free(type); free(role); ERR(handle, "could not create context structure"); return STATUS_ERR; } /* * Create a record from the given context structure */ int context_to_record(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, sepol_context_t ** record) { sepol_context_t *tmp_record = NULL; char *mls = NULL; if (sepol_context_create(handle, &tmp_record) < 0) goto err; if (sepol_context_set_user(handle, tmp_record, policydb->p_user_val_to_name[context->user - 1]) < 0) goto err; if (sepol_context_set_role(handle, tmp_record, policydb->p_role_val_to_name[context->role - 1]) < 0) goto err; if (sepol_context_set_type(handle, tmp_record, policydb->p_type_val_to_name[context->type - 1]) < 0) goto err; if (policydb->mls) { if (mls_to_string(handle, policydb, context, &mls) < 0) goto err; if (sepol_context_set_mls(handle, tmp_record, mls) < 0) goto err; } free(mls); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not create context record"); sepol_context_free(tmp_record); free(mls); return STATUS_ERR; } /* * Create a context structure from the provided string. */ int context_from_string(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const char *con_str, size_t con_str_len) { char *con_cpy = NULL; sepol_context_t *ctx_record = NULL; if (zero_or_saturated(con_str_len)) { ERR(handle, "Invalid context length"); goto err; } /* sepol_context_from_string expects a NULL-terminated string */ con_cpy = malloc(con_str_len + 1); if (!con_cpy) { ERR(handle, "out of memory"); goto err; } memcpy(con_cpy, con_str, con_str_len); con_cpy[con_str_len] = '\0'; if (sepol_context_from_string(handle, con_cpy, &ctx_record) < 0) goto err; /* Now create from the data structure */ if (context_from_record(handle, policydb, cptr, ctx_record) < 0) goto err; free(con_cpy); sepol_context_free(ctx_record); return STATUS_SUCCESS; err: ERR(handle, "could not create context structure"); free(con_cpy); sepol_context_free(ctx_record); return STATUS_ERR; } int sepol_context_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_context_t * context) { context_struct_t *con = NULL; int ret = context_from_record(handle, &policydb->p, &con, context); context_destroy(con); free(con); return ret; } libsepol/src/context.h0100644 0000000 0000000 00000002347 13756670065 014067 0ustar000000000 0000000 #ifndef _SEPOL_INTERNAL_CONTEXT_H_ #define _SEPOL_INTERNAL_CONTEXT_H_ #include #include "context_internal.h" #include #include #include /* Create a context structure from high level representation */ extern int context_from_record(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const sepol_context_t * data); extern int context_to_record(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, sepol_context_t ** record); /* Create a context structure from string representation */ extern int context_from_string(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const char *con_str, size_t con_str_len); /* Check if the provided context is valid for this policy */ extern int context_is_valid(const policydb_t * policydb, const context_struct_t * context); /* Extract the context as string */ extern int context_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, char **result, size_t * result_len); #endif libsepol/src/context_internal.h0100644 0000000 0000000 00000001142 13756670065 015753 0ustar000000000 0000000 #ifndef _SEPOL_CONTEXT_INTERNAL_H_ #define _SEPOL_CONTEXT_INTERNAL_H_ #include #include "dso.h" hidden_proto(sepol_context_clone) hidden_proto(sepol_context_create) hidden_proto(sepol_context_free) hidden_proto(sepol_context_from_string) hidden_proto(sepol_context_get_mls) hidden_proto(sepol_context_get_role) hidden_proto(sepol_context_get_type) hidden_proto(sepol_context_get_user) hidden_proto(sepol_context_set_mls) hidden_proto(sepol_context_set_role) hidden_proto(sepol_context_set_type) hidden_proto(sepol_context_set_user) #endif libsepol/src/context_record.c0100644 0000000 0000000 00000014754 13756670065 015425 0ustar000000000 0000000 #include #include #include #include #include "context_internal.h" #include "debug.h" #include "private.h" struct sepol_context { /* Selinux user */ char *user; /* Selinux role */ char *role; /* Selinux type */ char *type; /* MLS */ char *mls; }; /* User */ const char *sepol_context_get_user(const sepol_context_t * con) { return con->user; } hidden_def(sepol_context_get_user) int sepol_context_set_user(sepol_handle_t * handle, sepol_context_t * con, const char *user) { char *tmp_user = strdup(user); if (!tmp_user) { ERR(handle, "out of memory, could not set " "context user to %s", user); return STATUS_ERR; } free(con->user); con->user = tmp_user; return STATUS_SUCCESS; } hidden_def(sepol_context_set_user) /* Role */ const char *sepol_context_get_role(const sepol_context_t * con) { return con->role; } hidden_def(sepol_context_get_role) int sepol_context_set_role(sepol_handle_t * handle, sepol_context_t * con, const char *role) { char *tmp_role = strdup(role); if (!tmp_role) { ERR(handle, "out of memory, could not set " "context role to %s", role); return STATUS_ERR; } free(con->role); con->role = tmp_role; return STATUS_SUCCESS; } hidden_def(sepol_context_set_role) /* Type */ const char *sepol_context_get_type(const sepol_context_t * con) { return con->type; } hidden_def(sepol_context_get_type) int sepol_context_set_type(sepol_handle_t * handle, sepol_context_t * con, const char *type) { char *tmp_type = strdup(type); if (!tmp_type) { ERR(handle, "out of memory, could not set " "context type to %s", type); return STATUS_ERR; } free(con->type); con->type = tmp_type; return STATUS_SUCCESS; } hidden_def(sepol_context_set_type) /* MLS */ const char *sepol_context_get_mls(const sepol_context_t * con) { return con->mls; } hidden_def(sepol_context_get_mls) int sepol_context_set_mls(sepol_handle_t * handle, sepol_context_t * con, const char *mls) { char *tmp_mls = strdup(mls); if (!tmp_mls) { ERR(handle, "out of memory, could not set " "MLS fields to %s", mls); return STATUS_ERR; } free(con->mls); con->mls = tmp_mls; return STATUS_SUCCESS; } hidden_def(sepol_context_set_mls) /* Create */ int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr) { sepol_context_t *con = (sepol_context_t *) malloc(sizeof(sepol_context_t)); if (!con) { ERR(handle, "out of memory, could not " "create context\n"); return STATUS_ERR; } con->user = NULL; con->role = NULL; con->type = NULL; con->mls = NULL; *con_ptr = con; return STATUS_SUCCESS; } hidden_def(sepol_context_create) /* Deep copy clone */ int sepol_context_clone(sepol_handle_t * handle, const sepol_context_t * con, sepol_context_t ** con_ptr) { sepol_context_t *new_con = NULL; if (!con) { *con_ptr = NULL; return 0; } if (sepol_context_create(handle, &new_con) < 0) goto err; if (!(new_con->user = strdup(con->user))) goto omem; if (!(new_con->role = strdup(con->role))) goto omem; if (!(new_con->type = strdup(con->type))) goto omem; if (con->mls && !(new_con->mls = strdup(con->mls))) goto omem; *con_ptr = new_con; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone context record"); sepol_context_free(new_con); return STATUS_ERR; } hidden_def(sepol_context_clone) /* Destroy */ void sepol_context_free(sepol_context_t * con) { if (!con) return; free(con->user); free(con->role); free(con->type); free(con->mls); free(con); } hidden_def(sepol_context_free) int sepol_context_from_string(sepol_handle_t * handle, const char *str, sepol_context_t ** con) { char *tmp = NULL, *low, *high; sepol_context_t *tmp_con = NULL; if (!strcmp(str, "<>")) { *con = NULL; return STATUS_SUCCESS; } if (sepol_context_create(handle, &tmp_con) < 0) goto err; /* Working copy context */ tmp = strdup(str); if (!tmp) { ERR(handle, "out of memory"); goto err; } low = tmp; /* Then, break it into its components */ /* User */ if (!(high = strchr(low, ':'))) goto mcontext; else *high++ = '\0'; if (sepol_context_set_user(handle, tmp_con, low) < 0) goto err; low = high; /* Role */ if (!(high = strchr(low, ':'))) goto mcontext; else *high++ = '\0'; if (sepol_context_set_role(handle, tmp_con, low) < 0) goto err; low = high; /* Type, and possibly MLS */ if (!(high = strchr(low, ':'))) { if (sepol_context_set_type(handle, tmp_con, low) < 0) goto err; } else { *high++ = '\0'; if (sepol_context_set_type(handle, tmp_con, low) < 0) goto err; low = high; if (sepol_context_set_mls(handle, tmp_con, low) < 0) goto err; } free(tmp); *con = tmp_con; return STATUS_SUCCESS; mcontext: errno = EINVAL; ERR(handle, "malformed context \"%s\"", str); err: ERR(handle, "could not construct context from string"); free(tmp); sepol_context_free(tmp_con); return STATUS_ERR; } hidden_def(sepol_context_from_string) static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) { size_t a, i; *sum = 0; for(i=0; i < cnt; i++) { /* sum should not be smaller than the addend */ a = augends[i]; *sum += a; if (*sum < a) { return i; } } return 0; } int sepol_context_to_string(sepol_handle_t * handle, const sepol_context_t * con, char **str_ptr) { int rc; char *str = NULL; size_t total_sz, err; const size_t sizes[] = { strlen(con->user), /* user length */ strlen(con->role), /* role length */ strlen(con->type), /* type length */ (con->mls) ? strlen(con->mls) : 0, /* mls length */ ((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */ }; err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes)); if (err) { ERR(handle, "invalid size, overflow at position: %zu", err); goto err; } str = (char *)malloc(total_sz); if (!str) { ERR(handle, "out of memory"); goto err; } if (con->mls) { rc = snprintf(str, total_sz, "%s:%s:%s:%s", con->user, con->role, con->type, con->mls); } else { rc = snprintf(str, total_sz, "%s:%s:%s", con->user, con->role, con->type); } /* * rc is >= 0 on the size_t cast and is safe to promote * to an unsigned value. */ if (rc < 0 || (size_t)rc >= total_sz) { ERR(handle, "print error"); goto err; } *str_ptr = str; return STATUS_SUCCESS; err: ERR(handle, "could not convert context to string"); free(str); return STATUS_ERR; } libsepol/src/debug.c0100644 0000000 0000000 00000003242 13756670065 013457 0ustar000000000 0000000 #include #include #include #include "handle.h" #include "debug.h" /* Deprecated */ struct sepol_handle sepol_compat_handle = { .msg_callback = sepol_msg_default_handler, .msg_callback_arg = NULL, }; void sepol_debug(int on) { sepol_compat_handle.msg_callback = (on) ? sepol_msg_default_handler : NULL; } /* End deprecated */ int sepol_msg_get_level(sepol_handle_t * handle) { return handle->msg_level; } hidden_def(sepol_msg_get_level) const char *sepol_msg_get_channel(sepol_handle_t * handle) { return handle->msg_channel; } hidden_def(sepol_msg_get_channel) const char *sepol_msg_get_fname(sepol_handle_t * handle) { return handle->msg_fname; } hidden_def(sepol_msg_get_fname) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void hidden sepol_msg_default_handler(void *varg __attribute__ ((unused)), sepol_handle_t * handle, const char *fmt, ...) { FILE *stream = NULL; switch (sepol_msg_get_level(handle)) { case SEPOL_MSG_ERR: case SEPOL_MSG_WARN: stream = stderr; break; case SEPOL_MSG_INFO: default: stream = stdout; break; } fprintf(stream, "%s.%s: ", sepol_msg_get_channel(handle), sepol_msg_get_fname(handle)); va_list ap; va_start(ap, fmt); vfprintf(stream, fmt, ap); va_end(ap); fprintf(stream, "\n"); } extern void sepol_msg_set_callback(sepol_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...), void *msg_callback_arg) { handle->msg_callback = msg_callback; handle->msg_callback_arg = msg_callback_arg; } libsepol/src/debug.h0100644 0000000 0000000 00000004617 13756670065 013473 0ustar000000000 0000000 /* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_INTERNAL_DEBUG_H_ #define _SEPOL_INTERNAL_DEBUG_H_ #include #include #include "dso.h" #include "handle.h" #define STATUS_SUCCESS 0 #define STATUS_ERR -1 #define STATUS_NODATA 1 /* FIXME: this needs to become a real function. Declaring variables * in a macro is _evil_ as it can shadow other variables in local scope. * The variable h has been renamed to _sepol_h to reduce this chance, but * it is still wrong. */ #define msg_write(handle_arg, level_arg, \ channel_arg, func_arg, ...) do { \ sepol_handle_t *_sepol_h = (handle_arg) ?: &sepol_compat_handle; \ if (_sepol_h->msg_callback) { \ _sepol_h->msg_fname = func_arg; \ _sepol_h->msg_channel = channel_arg; \ _sepol_h->msg_level = level_arg; \ \ _sepol_h->msg_callback( \ _sepol_h->msg_callback_arg, \ _sepol_h, __VA_ARGS__); \ } \ } while(0) #define ERR(handle, ...) \ msg_write(handle, SEPOL_MSG_ERR, "libsepol", \ __FUNCTION__, __VA_ARGS__) #define INFO(handle, ...) \ msg_write(handle, SEPOL_MSG_INFO, "libsepol", \ __FUNCTION__, __VA_ARGS__) #define WARN(handle, ...) \ msg_write(handle, SEPOL_MSG_WARN, "libsepol", \ __FUNCTION__, __VA_ARGS__) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif extern void hidden sepol_msg_default_handler(void *varg, sepol_handle_t * msg, const char *fmt, ...); extern struct sepol_handle sepol_compat_handle; hidden_proto(sepol_msg_get_channel) hidden_proto(sepol_msg_get_fname) hidden_proto(sepol_msg_get_level) #endif libsepol/src/dso.h0100644 0000000 0000000 00000001322 13756670065 013160 0ustar000000000 0000000 #ifndef _SEPOL_DSO_H #define _SEPOL_DSO_H 1 #if !defined(SHARED) || defined(ANDROID) #define DISABLE_SYMVER 1 #endif #ifdef SHARED # define hidden __attribute__ ((visibility ("hidden"))) # define hidden_proto(fct) __hidden_proto (fct, fct##_internal) # define __hidden_proto(fct, internal) \ extern __typeof (fct) internal; \ extern __typeof (fct) fct __asm (#internal) hidden; # if defined(__alpha__) || defined(__mips__) # define hidden_def(fct) \ asm (".globl " #fct "\n" #fct " = " #fct "_internal"); # else # define hidden_def(fct) \ asm (".globl " #fct "\n.set " #fct ", " #fct "_internal"); #endif #else # define hidden # define hidden_proto(fct) # define hidden_def(fct) #endif #endif libsepol/src/ebitmap.c0100644 0000000 0000000 00000021622 13756670065 014014 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the extensible bitmap type. */ #include #include #include #include "debug.h" #include "private.h" int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) { ebitmap_node_t *n1, *n2, *new, *prev; ebitmap_init(dst); n1 = e1->node; n2 = e2->node; prev = 0; while (n1 || n2) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } memset(new, 0, sizeof(ebitmap_node_t)); if (n1 && n2 && n1->startbit == n2->startbit) { new->startbit = n1->startbit; new->map = n1->map | n2->map; n1 = n1->next; n2 = n2->next; } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { new->startbit = n1->startbit; new->map = n1->map; n1 = n1->next; } else { new->startbit = n2->startbit; new->map = n2->map; n2 = n2->next; } new->next = 0; if (prev) prev->next = new; else dst->node = new; prev = new; } dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; return 0; } int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) { ebitmap_t tmp; if (ebitmap_or(&tmp, dst, e1)) return -1; ebitmap_destroy(dst); dst->node = tmp.node; dst->highbit = tmp.highbit; return 0; } int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) { unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2)); ebitmap_init(dst); for (i=0; i < length; i++) { if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) { int rc = ebitmap_set_bit(dst, i, 1); if (rc < 0) return rc; } } return 0; } int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) { unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2)); ebitmap_init(dst); for (i=0; i < length; i++) { int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i); int rc = ebitmap_set_bit(dst, i, val); if (rc < 0) return rc; } return 0; } int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit) { unsigned int i; ebitmap_init(dst); for (i=0; i < maxbit; i++) { int val = ebitmap_get_bit(e1, i); int rc = ebitmap_set_bit(dst, i, !val); if (rc < 0) return rc; } return 0; } int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit) { ebitmap_t e3; ebitmap_init(dst); int rc = ebitmap_not(&e3, e2, maxbit); if (rc < 0) return rc; rc = ebitmap_and(dst, e1, &e3); ebitmap_destroy(&e3); if (rc < 0) return rc; return 0; } unsigned int ebitmap_cardinality(ebitmap_t *e1) { unsigned int i, count = 0; for (i=ebitmap_startbit(e1); i < ebitmap_length(e1); i++) if (ebitmap_get_bit(e1, i)) count++; return count; } int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2) { if (ebitmap_cmp(e1, e2)) return 0; ebitmap_t tmp; int rc = ebitmap_xor(&tmp, e1, e2); if (rc < 0) return -1; int distance = ebitmap_cardinality(&tmp); ebitmap_destroy(&tmp); return distance; } int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2) { ebitmap_node_t *n1, *n2; if (e1->highbit != e2->highbit) return 0; n1 = e1->node; n2 = e2->node; while (n1 && n2 && (n1->startbit == n2->startbit) && (n1->map == n2->map)) { n1 = n1->next; n2 = n2->next; } if (n1 || n2) return 0; return 1; } int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) { ebitmap_node_t *n, *new, *prev; ebitmap_init(dst); n = src->node; prev = 0; while (n) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } memset(new, 0, sizeof(ebitmap_node_t)); new->startbit = n->startbit; new->map = n->map; new->next = 0; if (prev) prev->next = new; else dst->node = new; prev = new; n = n->next; } dst->highbit = src->highbit; return 0; } int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2) { ebitmap_node_t *n1, *n2; if (e1->highbit < e2->highbit) return 0; n1 = e1->node; n2 = e2->node; while (n1 && n2 && (n1->startbit <= n2->startbit)) { if (n1->startbit < n2->startbit) { n1 = n1->next; continue; } if ((n1->map & n2->map) != n2->map) return 0; n1 = n1->next; n2 = n2->next; } if (n2) return 0; return 1; } int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2) { ebitmap_node_t *n1 = e1->node; ebitmap_node_t *n2 = e2->node; while (n1 && n2) { if (n1->startbit < n2->startbit) { n1 = n1->next; } else if (n2->startbit < n1->startbit) { n2 = n2->next; } else { if (n1->map & n2->map) { return 1; } n1 = n1->next; n2 = n2->next; } } return 0; } int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit) { ebitmap_node_t *n; if (e->highbit < bit) return 0; n = e->node; while (n && (n->startbit <= bit)) { if ((n->startbit + MAPSIZE) > bit) { if (n->map & (MAPBIT << (bit - n->startbit))) return 1; else return 0; } n = n->next; } return 0; } int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) { ebitmap_node_t *n, *prev, *new; uint32_t startbit = bit & ~(MAPSIZE - 1); uint32_t highbit = startbit + MAPSIZE; if (highbit == 0) { ERR(NULL, "bitmap overflow, bit 0x%x", bit); return -EINVAL; } prev = 0; n = e->node; while (n && n->startbit <= bit) { if ((n->startbit + MAPSIZE) > bit) { if (value) { n->map |= (MAPBIT << (bit - n->startbit)); } else { n->map &= ~(MAPBIT << (bit - n->startbit)); if (!n->map) { /* drop this node from the bitmap */ if (!n->next) { /* * this was the highest map * within the bitmap */ if (prev) e->highbit = prev->startbit + MAPSIZE; else e->highbit = 0; } if (prev) prev->next = n->next; else e->node = n->next; free(n); } } return 0; } prev = n; n = n->next; } if (!value) return 0; new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) return -ENOMEM; memset(new, 0, sizeof(ebitmap_node_t)); new->startbit = startbit; new->map = (MAPBIT << (bit - new->startbit)); if (!n) { /* this node will be the highest map within the bitmap */ e->highbit = highbit; } if (prev) { new->next = prev->next; prev->next = new; } else { new->next = e->node; e->node = new; } return 0; } void ebitmap_destroy(ebitmap_t * e) { ebitmap_node_t *n, *temp; if (!e) return; n = e->node; while (n) { temp = n; n = n->next; free(temp); } e->highbit = 0; e->node = 0; return; } int ebitmap_read(ebitmap_t * e, void *fp) { int rc; ebitmap_node_t *n, *l; uint32_t buf[3], mapsize, count, i; uint64_t map; ebitmap_init(e); rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto bad; mapsize = le32_to_cpu(buf[0]); e->highbit = le32_to_cpu(buf[1]); count = le32_to_cpu(buf[2]); if (mapsize != MAPSIZE) { printf ("security: ebitmap: map size %d does not match my size %zu (high bit was %d)\n", mapsize, MAPSIZE, e->highbit); goto bad; } if (!e->highbit) { e->node = NULL; goto ok; } if (e->highbit & (MAPSIZE - 1)) { printf ("security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)\n", e->highbit, MAPSIZE); goto bad; } if (e->highbit && !count) goto bad; l = NULL; for (i = 0; i < count; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { printf("security: ebitmap: truncated map\n"); goto bad; } n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!n) { printf("security: ebitmap: out of memory\n"); rc = -ENOMEM; goto bad; } memset(n, 0, sizeof(ebitmap_node_t)); n->startbit = le32_to_cpu(buf[0]); if (n->startbit & (MAPSIZE - 1)) { printf ("security: ebitmap start bit (%d) is not a multiple of the map size (%zu)\n", n->startbit, MAPSIZE); goto bad_free; } if (n->startbit > (e->highbit - MAPSIZE)) { printf ("security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)\n", n->startbit, (e->highbit - MAPSIZE)); goto bad_free; } rc = next_entry(&map, fp, sizeof(uint64_t)); if (rc < 0) { printf("security: ebitmap: truncated map\n"); goto bad_free; } n->map = le64_to_cpu(map); if (!n->map) { printf ("security: ebitmap: null map in ebitmap (startbit %d)\n", n->startbit); goto bad_free; } if (l) { if (n->startbit <= l->startbit) { printf ("security: ebitmap: start bit %d comes after start bit %d\n", n->startbit, l->startbit); goto bad_free; } l->next = n; } else e->node = n; l = n; } if (count && l->startbit + MAPSIZE != e->highbit) { printf ("security: ebitmap: hight bit %u has not the expected value %zu\n", e->highbit, l->startbit + MAPSIZE); goto bad; } ok: rc = 0; out: return rc; bad_free: free(n); bad: if (!rc) rc = -EINVAL; ebitmap_destroy(e); goto out; } /* FLASK */ libsepol/src/expand.c0100644 0000000 0000000 00000256055 13756670065 013664 0ustar000000000 0000000 /* Authors: Karl MacMillan * Jason Tang * Joshua Brindle * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2007 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "context.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" typedef struct expand_state { int verbose; uint32_t *typemap; uint32_t *boolmap; uint32_t *rolemap; uint32_t *usermap; policydb_t *base; policydb_t *out; sepol_handle_t *handle; int expand_neverallow; } expand_state_t; static void expand_state_init(expand_state_t * state) { memset(state, 0, sizeof(expand_state_t)); } static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map) { unsigned int i; ebitmap_node_t *tnode; ebitmap_init(dst); ebitmap_for_each_bit(src, tnode, i) { if (!ebitmap_node_get_bit(tnode, i)) continue; if (!map[i]) continue; if (ebitmap_set_bit(dst, map[i] - 1, 1)) return -1; } return 0; } static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; type_datum_t *type, *new_type; expand_state_t *state; id = (char *)key; type = (type_datum_t *) datum; state = (expand_state_t *) data; if ((type->flavor == TYPE_TYPE && !type->primary) || type->flavor == TYPE_ALIAS) { /* aliases are handled later */ return 0; } if (!is_id_enabled(id, state->base, SYM_TYPES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying type or attribute %s", id); new_id = strdup(id); if (new_id == NULL) { ERR(state->handle, "Out of memory!"); return -1; } new_type = (type_datum_t *) malloc(sizeof(type_datum_t)); if (!new_type) { ERR(state->handle, "Out of memory!"); free(new_id); return SEPOL_ENOMEM; } memset(new_type, 0, sizeof(type_datum_t)); new_type->flavor = type->flavor; new_type->flags = type->flags; new_type->s.value = ++state->out->p_types.nprim; if (new_type->s.value > UINT16_MAX) { free(new_id); free(new_type); ERR(state->handle, "type space overflow"); return -1; } new_type->primary = 1; state->typemap[type->s.value - 1] = new_type->s.value; ret = hashtab_insert(state->out->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_type); if (ret) { free(new_id); free(new_type); ERR(state->handle, "hashtab overflow"); return -1; } if (new_type->flags & TYPE_FLAGS_PERMISSIVE) if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) { ERR(state->handle, "Out of memory!\n"); return -1; } return 0; } static int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id; type_datum_t *type, *new_type; expand_state_t *state; ebitmap_t tmp_union; id = (char *)key; type = (type_datum_t *) datum; state = (expand_state_t *) data; if (type->flavor != TYPE_ATTRIB) return 0; if (!is_id_enabled(id, state->base, SYM_TYPES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "converting attribute %s", id); new_type = hashtab_search(state->out->p_types.table, id); if (!new_type) { ERR(state->handle, "attribute %s vanished!", id); return -1; } if (map_ebitmap(&type->types, &tmp_union, state->typemap)) { ERR(state->handle, "out of memory"); return -1; } /* then union tmp_union onto &new_type->types */ if (ebitmap_union(&new_type->types, &tmp_union)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_destroy(&tmp_union); return 0; } static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; symtab_t *s; perm_datum_t *perm, *new_perm; id = key; perm = (perm_datum_t *) datum; s = (symtab_t *) data; new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t)); if (!new_perm) { return -1; } memset(new_perm, 0, sizeof(perm_datum_t)); new_id = strdup(id); if (!new_id) { free(new_perm); return -1; } new_perm->s.value = perm->s.value; s->nprim++; ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm); if (ret) { free(new_id); free(new_perm); return -1; } return 0; } static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; common_datum_t *common, *new_common; expand_state_t *state; id = (char *)key; common = (common_datum_t *) datum; state = (expand_state_t *) data; if (state->verbose) INFO(state->handle, "copying common %s", id); new_common = (common_datum_t *) malloc(sizeof(common_datum_t)); if (!new_common) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_common, 0, sizeof(common_datum_t)); if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) { ERR(state->handle, "Out of memory!"); free(new_common); return -1; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); /* free memory created by symtab_init first, then free new_common */ symtab_destroy(&new_common->permissions); free(new_common); return -1; } new_common->s.value = common->s.value; state->out->p_commons.nprim++; ret = hashtab_insert(state->out->p_commons.table, new_id, (hashtab_datum_t *) new_common); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_common); free(new_id); return -1; } if (hashtab_map (common->permissions.table, perm_copy_callback, &new_common->permissions)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int constraint_node_clone(constraint_node_t ** dst, constraint_node_t * src, expand_state_t * state) { constraint_node_t *new_con = NULL, *last_new_con = NULL; constraint_expr_t *new_expr = NULL; *dst = NULL; while (src != NULL) { constraint_expr_t *expr, *expr_l = NULL; new_con = (constraint_node_t *) malloc(sizeof(constraint_node_t)); if (!new_con) { goto out_of_mem; } memset(new_con, 0, sizeof(constraint_node_t)); new_con->permissions = src->permissions; for (expr = src->expr; expr; expr = expr->next) { if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) { goto out_of_mem; } if (constraint_expr_init(new_expr) == -1) { goto out_of_mem; } new_expr->expr_type = expr->expr_type; new_expr->attr = expr->attr; new_expr->op = expr->op; if (new_expr->expr_type == CEXPR_NAMES) { if (new_expr->attr & CEXPR_TYPE) { /* * Copy over constraint policy source types and/or * attributes for sepol_compute_av_reason_buffer(3) * so that utilities can analyse constraint errors. */ if (map_ebitmap(&expr->type_names->types, &new_expr->type_names->types, state->typemap)) { ERR(NULL, "Failed to map type_names->types"); goto out_of_mem; } /* Type sets require expansion and conversion. */ if (expand_convert_type_set(state->out, state-> typemap, expr-> type_names, &new_expr-> names, 1)) { goto out_of_mem; } } else if (new_expr->attr & CEXPR_ROLE) { if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) { goto out_of_mem; } } else if (new_expr->attr & CEXPR_USER) { if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) { goto out_of_mem; } } else { /* Other kinds of sets do not. */ if (ebitmap_cpy(&new_expr->names, &expr->names)) { goto out_of_mem; } } } if (expr_l) { expr_l->next = new_expr; } else { new_con->expr = new_expr; } expr_l = new_expr; new_expr = NULL; } if (last_new_con == NULL) { *dst = new_con; } else { last_new_con->next = new_con; } last_new_con = new_con; src = src->next; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); if (new_con) free(new_con); constraint_expr_destroy(new_expr); return -1; } static int class_copy_default_new_object(expand_state_t *state, class_datum_t *olddatum, class_datum_t *newdatum) { if (olddatum->default_user) { if (newdatum->default_user && olddatum->default_user != newdatum->default_user) { ERR(state->handle, "Found conflicting default user definitions"); return SEPOL_ENOTSUP; } newdatum->default_user = olddatum->default_user; } if (olddatum->default_role) { if (newdatum->default_role && olddatum->default_role != newdatum->default_role) { ERR(state->handle, "Found conflicting default role definitions"); return SEPOL_ENOTSUP; } newdatum->default_role = olddatum->default_role; } if (olddatum->default_type) { if (newdatum->default_type && olddatum->default_type != newdatum->default_type) { ERR(state->handle, "Found conflicting default type definitions"); return SEPOL_ENOTSUP; } newdatum->default_type = olddatum->default_type; } if (olddatum->default_range) { if (newdatum->default_range && olddatum->default_range != newdatum->default_range) { ERR(state->handle, "Found conflicting default range definitions"); return SEPOL_ENOTSUP; } newdatum->default_range = olddatum->default_range; } return 0; } static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; class_datum_t *class, *new_class; expand_state_t *state; id = (char *)key; class = (class_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_CLASSES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying class %s", id); new_class = (class_datum_t *) malloc(sizeof(class_datum_t)); if (!new_class) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_class, 0, sizeof(class_datum_t)); if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) { ERR(state->handle, "Out of memory!"); free(new_class); return -1; } new_class->s.value = class->s.value; state->out->p_classes.nprim++; ret = class_copy_default_new_object(state, class, new_class); if (ret) { free(new_class); return ret; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_class); return -1; } ret = hashtab_insert(state->out->p_classes.table, new_id, (hashtab_datum_t *) new_class); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_class); free(new_id); return -1; } if (hashtab_map (class->permissions.table, perm_copy_callback, &new_class->permissions)) { ERR(state->handle, "hashtab overflow"); return -1; } if (class->comkey) { new_class->comkey = strdup(class->comkey); if (!new_class->comkey) { ERR(state->handle, "Out of memory!"); return -1; } new_class->comdatum = hashtab_search(state->out->p_commons.table, new_class->comkey); if (!new_class->comdatum) { ERR(state->handle, "could not find common datum %s", new_class->comkey); return -1; } new_class->permissions.nprim += new_class->comdatum->permissions.nprim; } return 0; } static int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id; class_datum_t *class, *new_class; expand_state_t *state; id = (char *)key; class = (class_datum_t *) datum; state = (expand_state_t *) data; new_class = hashtab_search(state->out->p_classes.table, id); if (!new_class) { ERR(state->handle, "class %s vanished", id); return -1; } /* constraints */ if (constraint_node_clone (&new_class->constraints, class->constraints, state) == -1 || constraint_node_clone(&new_class->validatetrans, class->validatetrans, state) == -1) { return -1; } return 0; } /* * The boundaries have to be copied after the types/roles/users are copied, * because it refers hashtab to lookup destinated objects. */ static int type_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; type_datum_t *type = (type_datum_t *) datum; type_datum_t *dest; uint32_t bounds_val; if (!type->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_TYPES)) return 0; bounds_val = state->typemap[type->bounds - 1]; dest = hashtab_search(state->out->p_types.table, (char *)key); if (!dest) { ERR(state->handle, "Type lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int role_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; role_datum_t *role = (role_datum_t *) datum; role_datum_t *dest; uint32_t bounds_val; if (!role->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_ROLES)) return 0; bounds_val = state->rolemap[role->bounds - 1]; dest = hashtab_search(state->out->p_roles.table, (char *)key); if (!dest) { ERR(state->handle, "Role lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int user_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; user_datum_t *user = (user_datum_t *) datum; user_datum_t *dest; uint32_t bounds_val; if (!user->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_USERS)) return 0; bounds_val = state->usermap[user->bounds - 1]; dest = hashtab_search(state->out->p_users.table, (char *)key); if (!dest) { ERR(state->handle, "User lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } /* The aliases have to be copied after the types and attributes to be certain that * the out symbol table will have the type that the alias refers. Otherwise, we * won't be able to find the type value for the alias. We can't depend on the * declaration ordering because of the hash table. */ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; type_datum_t *alias, *new_alias; expand_state_t *state; uint32_t prival; id = (char *)key; alias = (type_datum_t *) datum; state = (expand_state_t *) data; /* ignore regular types */ if (alias->flavor == TYPE_TYPE && alias->primary) return 0; /* ignore attributes */ if (alias->flavor == TYPE_ATTRIB) return 0; if (alias->flavor == TYPE_ALIAS) prival = alias->primary; else prival = alias->s.value; if (!is_id_enabled(state->base->p_type_val_to_name[prival - 1], state->base, SYM_TYPES)) { /* The primary type for this alias is not enabled, the alias * shouldn't be either */ return 0; } if (state->verbose) INFO(state->handle, "copying alias %s", id); new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); return -1; } new_alias = (type_datum_t *) malloc(sizeof(type_datum_t)); if (!new_alias) { ERR(state->handle, "Out of memory!"); free(new_id); return SEPOL_ENOMEM; } memset(new_alias, 0, sizeof(type_datum_t)); if (alias->flavor == TYPE_TYPE) new_alias->s.value = state->typemap[alias->s.value - 1]; else if (alias->flavor == TYPE_ALIAS) new_alias->s.value = state->typemap[alias->primary - 1]; else assert(0); /* unreachable */ new_alias->flags = alias->flags; ret = hashtab_insert(state->out->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_alias); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_alias); free(new_id); return -1; } state->typemap[alias->s.value - 1] = new_alias->s.value; if (new_alias->flags & TYPE_FLAGS_PERMISSIVE) if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data) { ebitmap_t mapped_roles; role_datum_t *role = (role_datum_t *) datum; expand_state_t *state = (expand_state_t *) data; if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap)) return -1; ebitmap_destroy(&role->dominates); if (ebitmap_cpy(&role->dominates, &mapped_roles)) return -1; ebitmap_destroy(&mapped_roles); return 0; } /* For the role attribute in the base module, escalate its counterpart's * types.types ebitmap in the out module to the counterparts of all the * regular role that belongs to the current role attribute. Note, must be * invoked after role_copy_callback so that state->rolemap is available. */ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id, *base_reg_role_id; role_datum_t *role, *new_role, *regular_role; expand_state_t *state; ebitmap_node_t *rnode; unsigned int i; ebitmap_t mapped_roles; id = key; role = (role_datum_t *)datum; state = (expand_state_t *)data; if (strcmp(id, OBJECT_R) == 0) { /* object_r is never a role attribute by far */ return 0; } if (!is_id_enabled(id, state->base, SYM_ROLES)) { /* identifier's scope is not enabled */ return 0; } if (role->flavor != ROLE_ATTRIB) return 0; if (state->verbose) INFO(state->handle, "fixing role attribute %s", id); new_role = (role_datum_t *)hashtab_search(state->out->p_roles.table, id); assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB); ebitmap_init(&mapped_roles); if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap)) return -1; if (ebitmap_union(&new_role->roles, &mapped_roles)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&mapped_roles); return -1; } ebitmap_destroy(&mapped_roles); ebitmap_for_each_bit(&role->roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { /* take advantage of sym_val_to_name[] * of the base module */ base_reg_role_id = state->base->p_role_val_to_name[i]; regular_role = (role_datum_t *)hashtab_search( state->out->p_roles.table, base_reg_role_id); assert(regular_role != NULL && regular_role->flavor == ROLE_ROLE); if (ebitmap_union(®ular_role->types.types, &new_role->types.types)) { ERR(state->handle, "Out of memory!"); return -1; } } } return 0; } static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; role_datum_t *role; role_datum_t *new_role; expand_state_t *state; ebitmap_t tmp_union_types; id = key; role = (role_datum_t *) datum; state = (expand_state_t *) data; if (strcmp(id, OBJECT_R) == 0) { /* object_r is always value 1 */ state->rolemap[role->s.value - 1] = 1; return 0; } if (!is_id_enabled(id, state->base, SYM_ROLES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying role %s", id); new_role = (role_datum_t *) hashtab_search(state->out->p_roles.table, id); if (!new_role) { new_role = (role_datum_t *) malloc(sizeof(role_datum_t)); if (!new_role) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_role, 0, sizeof(role_datum_t)); new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_role); return -1; } state->out->p_roles.nprim++; new_role->flavor = role->flavor; new_role->s.value = state->out->p_roles.nprim; state->rolemap[role->s.value - 1] = new_role->s.value; ret = hashtab_insert(state->out->p_roles.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_role); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_role); free(new_id); return -1; } } /* The dominates bitmap is going to be wrong for the moment, * we'll come back later and remap them, after we are sure all * the roles have been added */ if (ebitmap_union(&new_role->dominates, &role->dominates)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_init(&tmp_union_types); /* convert types in the role datum in the global symtab */ if (expand_convert_type_set (state->out, state->typemap, &role->types, &tmp_union_types, 1)) { ebitmap_destroy(&tmp_union_types); ERR(state->handle, "Out of memory!"); return -1; } if (ebitmap_union(&new_role->types.types, &tmp_union_types)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union_types); return -1; } ebitmap_destroy(&tmp_union_types); return 0; } int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, policydb_t * p, sepol_handle_t * h) { mls_semantic_cat_t *cat; level_datum_t *levdatum; unsigned int i; mls_level_init(l); if (!p->mls) return 0; /* Required not declared. */ if (!sl->sens) return 0; l->sens = sl->sens; levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, p->p_sens_val_to_name[l->sens - 1]); if (!levdatum) { ERR(h, "%s: Impossible situation found, nothing in p_levels.table.\n", __func__); errno = ENOENT; return -1; } for (cat = sl->cat; cat; cat = cat->next) { if (cat->low > cat->high) { ERR(h, "Category range is not valid %s.%s", p->p_cat_val_to_name[cat->low - 1], p->p_cat_val_to_name[cat->high - 1]); return -1; } for (i = cat->low - 1; i < cat->high; i++) { if (!ebitmap_get_bit(&levdatum->level->cat, i)) { ERR(h, "Category %s can not be associated with " "level %s", p->p_cat_val_to_name[i], p->p_sens_val_to_name[l->sens - 1]); return -1; } if (ebitmap_set_bit(&l->cat, i, 1)) { ERR(h, "Out of memory!"); return -1; } } } return 0; } int mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r, policydb_t * p, sepol_handle_t * h) { if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0) return -1; if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) { mls_level_destroy(&r->level[0]); return -1; } if (!mls_level_dom(&r->level[1], &r->level[0])) { mls_range_destroy(r); ERR(h, "MLS range high level does not dominate low level"); return -1; } return 0; } static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; expand_state_t *state; user_datum_t *user; user_datum_t *new_user; char *id, *new_id; ebitmap_t tmp_union; id = key; user = (user_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_USERS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying user %s", id); new_user = (user_datum_t *) hashtab_search(state->out->p_users.table, id); if (!new_user) { new_user = (user_datum_t *) malloc(sizeof(user_datum_t)); if (!new_user) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_user, 0, sizeof(user_datum_t)); state->out->p_users.nprim++; new_user->s.value = state->out->p_users.nprim; state->usermap[user->s.value - 1] = new_user->s.value; new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_user); return -1; } ret = hashtab_insert(state->out->p_users.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_user); if (ret) { ERR(state->handle, "hashtab overflow"); user_datum_destroy(new_user); free(new_user); free(new_id); return -1; } /* expand the semantic MLS info */ if (mls_semantic_range_expand(&user->range, &new_user->exp_range, state->out, state->handle)) { return -1; } if (mls_semantic_level_expand(&user->dfltlevel, &new_user->exp_dfltlevel, state->out, state->handle)) { return -1; } if (!mls_level_between(&new_user->exp_dfltlevel, &new_user->exp_range.level[0], &new_user->exp_range.level[1])) { ERR(state->handle, "default level not within user " "range"); return -1; } } else { /* require that the MLS info match */ mls_range_t tmp_range; mls_level_t tmp_level; if (mls_semantic_range_expand(&user->range, &tmp_range, state->out, state->handle)) { return -1; } if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level, state->out, state->handle)) { mls_range_destroy(&tmp_range); return -1; } if (!mls_range_eq(&new_user->exp_range, &tmp_range) || !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) { mls_range_destroy(&tmp_range); mls_level_destroy(&tmp_level); return -1; } mls_range_destroy(&tmp_range); mls_level_destroy(&tmp_level); } ebitmap_init(&tmp_union); /* get global roles for this user */ if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union); return -1; } if (ebitmap_union(&new_user->roles.roles, &tmp_union)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union); return -1; } ebitmap_destroy(&tmp_union); return 0; } static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; expand_state_t *state; cond_bool_datum_t *bool, *new_bool; char *id, *new_id; id = key; bool = (cond_bool_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_BOOLS)) { /* identifier's scope is not enabled */ return 0; } if (bool->flags & COND_BOOL_FLAGS_TUNABLE) { /* Skip tunables */ return 0; } if (state->verbose) INFO(state->handle, "copying boolean %s", id); new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t)); if (!new_bool) { ERR(state->handle, "Out of memory!"); return -1; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_bool); return -1; } state->out->p_bools.nprim++; new_bool->s.value = state->out->p_bools.nprim; ret = hashtab_insert(state->out->p_bools.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_bool); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_bool); free(new_id); return -1; } state->boolmap[bool->s.value - 1] = new_bool->s.value; new_bool->state = bool->state; new_bool->flags = bool->flags; return 0; } static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; level_datum_t *level = (level_datum_t *) datum, *new_level = NULL; char *id = (char *)key, *new_id = NULL; if (!is_id_enabled(id, state->base, SYM_LEVELS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying sensitivity level %s", id); new_level = (level_datum_t *) malloc(sizeof(level_datum_t)); if (!new_level) goto out_of_mem; level_datum_init(new_level); new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t)); if (!new_level->level) goto out_of_mem; mls_level_init(new_level->level); new_id = strdup(id); if (!new_id) goto out_of_mem; if (mls_level_cpy(new_level->level, level->level)) { goto out_of_mem; } new_level->isalias = level->isalias; state->out->p_levels.nprim++; if (hashtab_insert(state->out->p_levels.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_level)) { goto out_of_mem; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); if (new_level != NULL && new_level->level != NULL) { mls_level_destroy(new_level->level); free(new_level->level); } level_datum_destroy(new_level); free(new_level); free(new_id); return -1; } static int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL; char *id = (char *)key, *new_id = NULL; if (!is_id_enabled(id, state->base, SYM_CATS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying category attribute %s", id); new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t)); if (!new_cat) goto out_of_mem; cat_datum_init(new_cat); new_id = strdup(id); if (!new_id) goto out_of_mem; new_cat->s.value = cat->s.value; new_cat->isalias = cat->isalias; state->out->p_cats.nprim++; if (hashtab_insert(state->out->p_cats.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) { goto out_of_mem; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); cat_datum_destroy(new_cat); free(new_cat); free(new_id); return -1; } static int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules) { unsigned int i, j; role_allow_t *cur_allow, *n, *l; role_allow_rule_t *cur; ebitmap_t roles, new_roles; ebitmap_node_t *snode, *tnode; /* start at the end of the list */ for (l = state->out->role_allow; l && l->next; l = l->next) ; cur = rules; while (cur) { ebitmap_init(&roles); ebitmap_init(&new_roles); if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_for_each_bit(&roles, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(&new_roles, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; /* check for duplicates */ cur_allow = state->out->role_allow; while (cur_allow) { if ((cur_allow->role == i + 1) && (cur_allow->new_role == j + 1)) break; cur_allow = cur_allow->next; } if (cur_allow) continue; n = (role_allow_t *) malloc(sizeof(role_allow_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(role_allow_t)); n->role = i + 1; n->new_role = j + 1; if (l) { l->next = n; } else { state->out->role_allow = n; } l = n; } } ebitmap_destroy(&roles); ebitmap_destroy(&new_roles); cur = cur->next; } return 0; } static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules) { unsigned int i, j, k; role_trans_t *n, *l, *cur_trans; role_trans_rule_t *cur; ebitmap_t roles, types; ebitmap_node_t *rnode, *tnode, *cnode; /* start at the end of the list */ for (l = state->out->role_tr; l && l->next; l = l->next) ; cur = rules; while (cur) { ebitmap_init(&roles); ebitmap_init(&types); if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set (state->out, state->typemap, &cur->types, &types, 1)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_for_each_bit(&roles, rnode, i) { if (!ebitmap_node_get_bit(rnode, i)) continue; ebitmap_for_each_bit(&types, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; ebitmap_for_each_bit(&cur->classes, cnode, k) { if (!ebitmap_node_get_bit(cnode, k)) continue; cur_trans = state->out->role_tr; while (cur_trans) { unsigned int mapped_role; mapped_role = state->rolemap[cur->new_role - 1]; if ((cur_trans->role == i + 1) && (cur_trans->type == j + 1) && (cur_trans->tclass == k + 1)) { if (cur_trans->new_role == mapped_role) { break; } else { ERR(state->handle, "Conflicting role trans rule %s %s : %s { %s vs %s }", state->out->p_role_val_to_name[i], state->out->p_type_val_to_name[j], state->out->p_class_val_to_name[k], state->out->p_role_val_to_name[mapped_role - 1], state->out->p_role_val_to_name[cur_trans->new_role - 1]); return -1; } } cur_trans = cur_trans->next; } if (cur_trans) continue; n = (role_trans_t *) malloc(sizeof(role_trans_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(role_trans_t)); n->role = i + 1; n->type = j + 1; n->tclass = k + 1; n->new_role = state->rolemap [cur->new_role - 1]; if (l) l->next = n; else state->out->role_tr = n; l = n; } } } ebitmap_destroy(&roles); ebitmap_destroy(&types); cur = cur->next; } return 0; } static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules) { unsigned int i, j; filename_trans_t key, *new_trans; filename_trans_datum_t *otype; filename_trans_rule_t *cur_rule; ebitmap_t stypes, ttypes; ebitmap_node_t *snode, *tnode; int rc; cur_rule = rules; while (cur_rule) { uint32_t mapped_otype; ebitmap_init(&stypes); ebitmap_init(&ttypes); if (expand_convert_type_set(state->out, state->typemap, &cur_rule->stypes, &stypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set(state->out, state->typemap, &cur_rule->ttypes, &ttypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } mapped_otype = state->typemap[cur_rule->otype - 1]; ebitmap_for_each_bit(&stypes, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(&ttypes, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; key.stype = i + 1; key.ttype = j + 1; key.tclass = cur_rule->tclass; key.name = cur_rule->name; otype = hashtab_search(state->out->filename_trans, (hashtab_key_t) &key); if (otype) { /* duplicate rule, ignore */ if (otype->otype == mapped_otype) continue; ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s", state->out->p_type_val_to_name[i], state->out->p_type_val_to_name[j], state->out->p_class_val_to_name[cur_rule->tclass - 1], cur_rule->name, state->out->p_type_val_to_name[otype->otype - 1], state->out->p_type_val_to_name[mapped_otype - 1]); return -1; } new_trans = calloc(1, sizeof(*new_trans)); if (!new_trans) { ERR(state->handle, "Out of memory!"); return -1; } new_trans->name = strdup(cur_rule->name); if (!new_trans->name) { ERR(state->handle, "Out of memory!"); free(new_trans); return -1; } new_trans->stype = i + 1; new_trans->ttype = j + 1; new_trans->tclass = cur_rule->tclass; otype = calloc(1, sizeof(*otype)); if (!otype) { ERR(state->handle, "Out of memory!"); free(new_trans->name); free(new_trans); return -1; } otype->otype = mapped_otype; rc = hashtab_insert(state->out->filename_trans, (hashtab_key_t)new_trans, otype); if (rc) { ERR(state->handle, "Out of memory!"); free(otype); free(new_trans->name); free(new_trans); return -1; } } } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); cur_rule = cur_rule->next; } return 0; } static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass, mls_semantic_range_t * trange, expand_state_t * state) { range_trans_t *rt = NULL, key; mls_range_t *r, *exp_range = NULL; int rc = -1; exp_range = calloc(1, sizeof(*exp_range)); if (!exp_range) { ERR(state->handle, "Out of memory!"); return -1; } if (mls_semantic_range_expand(trange, exp_range, state->out, state->handle)) goto err; /* check for duplicates/conflicts */ key.source_type = stype; key.target_type = ttype; key.target_class = tclass; r = hashtab_search(state->out->range_tr, (hashtab_key_t) &key); if (r) { if (mls_range_eq(r, exp_range)) { /* duplicate, ignore */ mls_range_destroy(exp_range); free(exp_range); return 0; } /* conflict */ ERR(state->handle, "Conflicting range trans rule %s %s : %s", state->out->p_type_val_to_name[stype - 1], state->out->p_type_val_to_name[ttype - 1], state->out->p_class_val_to_name[tclass - 1]); goto err; } rt = calloc(1, sizeof(*rt)); if (!rt) { ERR(state->handle, "Out of memory!"); goto err; } rt->source_type = stype; rt->target_type = ttype; rt->target_class = tclass; rc = hashtab_insert(state->out->range_tr, (hashtab_key_t) rt, exp_range); if (rc) { ERR(state->handle, "Out of memory!"); goto err; } return 0; err: free(rt); if (exp_range) { mls_range_destroy(exp_range); free(exp_range); } return -1; } static int expand_range_trans(expand_state_t * state, range_trans_rule_t * rules) { unsigned int i, j, k; range_trans_rule_t *rule; ebitmap_t stypes, ttypes; ebitmap_node_t *snode, *tnode, *cnode; if (state->verbose) INFO(state->handle, "expanding range transitions"); for (rule = rules; rule; rule = rule->next) { ebitmap_init(&stypes); ebitmap_init(&ttypes); /* expand the type sets */ if (expand_convert_type_set(state->out, state->typemap, &rule->stypes, &stypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set(state->out, state->typemap, &rule->ttypes, &ttypes, 1)) { ebitmap_destroy(&stypes); ERR(state->handle, "Out of memory!"); return -1; } /* loop on source type */ ebitmap_for_each_bit(&stypes, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; /* loop on target type */ ebitmap_for_each_bit(&ttypes, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; /* loop on target class */ ebitmap_for_each_bit(&rule->tclasses, cnode, k) { if (!ebitmap_node_get_bit(cnode, k)) continue; if (exp_rangetr_helper(i + 1, j + 1, k + 1, &rule->trange, state)) { ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return -1; } } } } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); } return 0; } /* Search for an AV tab node within a hash table with the given key. * If the node does not exist, create it and return it; otherwise * return the pre-existing one. */ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle, avtab_t * avtab, avtab_key_t * key, cond_av_list_t ** cond, av_extended_perms_t *xperms) { avtab_ptr_t node; avtab_datum_t avdatum; cond_av_list_t *nl; int match = 0; /* AVTAB_XPERMS entries are not necessarily unique */ if (key->specified & AVTAB_XPERMS) { node = avtab_search_node(avtab, key); while (node) { if ((node->datum.xperms->specified == xperms->specified) && (node->datum.xperms->driver == xperms->driver)) { match = 1; break; } node = avtab_search_node_next(node, key->specified); } if (!match) node = NULL; } else { node = avtab_search_node(avtab, key); } /* If this is for conditional policies, keep searching in case the node is part of my conditional avtab. */ if (cond) { while (node) { if (node->parse_context == cond) break; node = avtab_search_node_next(node, key->specified); } } if (!node) { memset(&avdatum, 0, sizeof avdatum); /* * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for * others. Initialize the data accordingly. */ avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0; /* this is used to get the node - insertion is actually unique */ node = avtab_insert_nonunique(avtab, key, &avdatum); if (!node) { ERR(handle, "hash table overflow"); return NULL; } if (cond) { node->parse_context = cond; nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t)); if (!nl) { ERR(handle, "Memory error"); return NULL; } memset(nl, 0, sizeof(cond_av_list_t)); nl->node = node; nl->next = *cond; *cond = nl; } } return node; } static uint32_t avrule_to_avtab_spec(uint32_t specification) { return (specification == AVRULE_DONTAUDIT) ? AVTAB_AUDITDENY : specification; } #define EXPAND_RULE_SUCCESS 1 #define EXPAND_RULE_CONFLICT 0 #define EXPAND_RULE_ERROR -1 static int expand_terule_helper(sepol_handle_t * handle, policydb_t * p, uint32_t * typemap, uint32_t specified, cond_av_list_t ** cond, cond_av_list_t ** other, uint32_t stype, uint32_t ttype, class_perm_node_t * perms, avtab_t * avtab, int enabled) { avtab_key_t avkey; avtab_datum_t *avdatump; avtab_ptr_t node; class_perm_node_t *cur; int conflict; uint32_t oldtype = 0; if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) { ERR(handle, "Invalid specification: %"PRIu32"\n", specified); return EXPAND_RULE_ERROR; } avkey.specified = avrule_to_avtab_spec(specified); avkey.source_type = stype + 1; avkey.target_type = ttype + 1; cur = perms; while (cur) { uint32_t remapped_data = typemap ? typemap[cur->data - 1] : cur->data; avkey.target_class = cur->tclass; conflict = 0; /* check to see if the expanded TE already exists -- * either in the global scope or in another * conditional AV tab */ node = avtab_search_node(&p->te_avtab, &avkey); if (node) { conflict = 1; } else { node = avtab_search_node(&p->te_cond_avtab, &avkey); if (node && node->parse_context != other) { conflict = 2; } } if (conflict) { avdatump = &node->datum; if (specified & AVRULE_TRANSITION) { oldtype = avdatump->data; } else if (specified & AVRULE_MEMBER) { oldtype = avdatump->data; } else if (specified & AVRULE_CHANGE) { oldtype = avdatump->data; } if (oldtype == remapped_data) { /* if the duplicate is inside the same scope (eg., unconditional * or in same conditional then ignore it */ if ((conflict == 1 && cond == NULL) || node->parse_context == cond) return EXPAND_RULE_SUCCESS; ERR(handle, "duplicate TE rule for %s %s:%s %s", p->p_type_val_to_name[avkey.source_type - 1], p->p_type_val_to_name[avkey.target_type - 1], p->p_class_val_to_name[avkey.target_class - 1], p->p_type_val_to_name[oldtype - 1]); return EXPAND_RULE_CONFLICT; } ERR(handle, "conflicting TE rule for (%s, %s:%s): old was %s, new is %s", p->p_type_val_to_name[avkey.source_type - 1], p->p_type_val_to_name[avkey.target_type - 1], p->p_class_val_to_name[avkey.target_class - 1], p->p_type_val_to_name[oldtype - 1], p->p_type_val_to_name[remapped_data - 1]); return EXPAND_RULE_CONFLICT; } node = find_avtab_node(handle, avtab, &avkey, cond, NULL); if (!node) return -1; if (enabled) { node->key.specified |= AVTAB_ENABLED; } else { node->key.specified &= ~AVTAB_ENABLED; } avdatump = &node->datum; avdatump->data = remapped_data; cur = cur->next; } return EXPAND_RULE_SUCCESS; } /* 0 for success -1 indicates failure */ static int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump, av_extended_perms_t * extended_perms) { unsigned int i; avtab_extended_perms_t *xperms = avdatump->xperms; if (!xperms) { xperms = (avtab_extended_perms_t *) calloc(1, sizeof(avtab_extended_perms_t)); if (!xperms) { ERR(handle, "Out of memory!"); return -1; } avdatump->xperms = xperms; } switch (extended_perms->specified) { case AVRULE_XPERMS_IOCTLFUNCTION: xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION; break; case AVRULE_XPERMS_IOCTLDRIVER: xperms->specified = AVTAB_XPERMS_IOCTLDRIVER; break; default: return -1; } xperms->driver = extended_perms->driver; for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) xperms->perms[i] |= extended_perms->perms[i]; return 0; } static int expand_avrule_helper(sepol_handle_t * handle, uint32_t specified, cond_av_list_t ** cond, uint32_t stype, uint32_t ttype, class_perm_node_t * perms, avtab_t * avtab, int enabled, av_extended_perms_t *extended_perms) { avtab_key_t avkey; avtab_datum_t *avdatump; avtab_ptr_t node; class_perm_node_t *cur; /* bail early if dontaudit's are disabled and it's a dontaudit rule */ if ((specified & (AVRULE_DONTAUDIT|AVRULE_XPERMS_DONTAUDIT)) && handle && handle->disable_dontaudit) return EXPAND_RULE_SUCCESS; avkey.source_type = stype + 1; avkey.target_type = ttype + 1; avkey.specified = avrule_to_avtab_spec(specified); cur = perms; while (cur) { avkey.target_class = cur->tclass; node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms); if (!node) return EXPAND_RULE_ERROR; if (enabled) { node->key.specified |= AVTAB_ENABLED; } else { node->key.specified &= ~AVTAB_ENABLED; } avdatump = &node->datum; switch (specified) { case AVRULE_ALLOWED: case AVRULE_AUDITALLOW: case AVRULE_NEVERALLOW: avdatump->data |= cur->data; break; case AVRULE_DONTAUDIT: avdatump->data &= ~cur->data; break; case AVRULE_AUDITDENY: /* Since a '0' in an auditdeny mask represents * a permission we do NOT want to audit * (dontaudit), we use the '&' operand to * ensure that all '0's in the mask are * retained (much unlike the allow and * auditallow cases). */ avdatump->data &= cur->data; break; case AVRULE_XPERMS_ALLOWED: case AVRULE_XPERMS_AUDITALLOW: case AVRULE_XPERMS_DONTAUDIT: case AVRULE_XPERMS_NEVERALLOW: if (allocate_xperms(handle, avdatump, extended_perms)) return EXPAND_RULE_ERROR; break; default: ERR(handle, "Unknown specification: %"PRIu32"\n", specified); return EXPAND_RULE_ERROR; } cur = cur->next; } return EXPAND_RULE_SUCCESS; } static int expand_rule_helper(sepol_handle_t * handle, policydb_t * p, uint32_t * typemap, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled, ebitmap_t * stypes, ebitmap_t * ttypes) { unsigned int i, j; int retval; ebitmap_node_t *snode, *tnode; ebitmap_for_each_bit(stypes, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; if (source_rule->flags & RULE_SELF) { if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { retval = expand_avrule_helper(handle, source_rule->specified, cond, i, i, source_rule->perms, dest_avtab, enabled, source_rule->xperms); if (retval != EXPAND_RULE_SUCCESS) return retval; } else { retval = expand_terule_helper(handle, p, typemap, source_rule->specified, cond, other, i, i, source_rule->perms, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; } } ebitmap_for_each_bit(ttypes, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { retval = expand_avrule_helper(handle, source_rule->specified, cond, i, j, source_rule->perms, dest_avtab, enabled, source_rule->xperms); if (retval != EXPAND_RULE_SUCCESS) return retval; } else { retval = expand_terule_helper(handle, p, typemap, source_rule->specified, cond, other, i, j, source_rule->perms, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; } } } return EXPAND_RULE_SUCCESS; } /* * Expand a rule into a given avtab - checking for conflicting type * rules in the destination policy. Return EXPAND_RULE_SUCCESS on * success, EXPAND_RULE_CONFLICT if the rule conflicts with something * (and hence was not added), or EXPAND_RULE_ERROR on error. */ static int convert_and_expand_rule(sepol_handle_t * handle, policydb_t * dest_pol, uint32_t * typemap, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled, int do_neverallow) { int retval; ebitmap_t stypes, ttypes; unsigned char alwaysexpand; if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW) return EXPAND_RULE_SUCCESS; if (!do_neverallow && source_rule->specified & AVRULE_XPERMS_NEVERALLOW) return EXPAND_RULE_SUCCESS; ebitmap_init(&stypes); ebitmap_init(&ttypes); /* Force expansion for type rules and for self rules. */ alwaysexpand = ((source_rule->specified & AVRULE_TYPE) || (source_rule->flags & RULE_SELF)); if (expand_convert_type_set (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand)) return EXPAND_RULE_ERROR; if (expand_convert_type_set (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand)) return EXPAND_RULE_ERROR; retval = expand_rule_helper(handle, dest_pol, typemap, source_rule, dest_avtab, cond, other, enabled, &stypes, &ttypes); ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return retval; } static int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules, avtab_t * dest_avtab, cond_av_list_t ** list, cond_av_list_t ** other, uint32_t * typemap, int enabled, expand_state_t * state) { avrule_t *cur; cur = source_rules; while (cur) { if (convert_and_expand_rule(state->handle, dest_pol, typemap, cur, dest_avtab, list, other, enabled, 0) != EXPAND_RULE_SUCCESS) { return -1; } cur = cur->next; } return 0; } static int cond_node_map_bools(expand_state_t * state, cond_node_t * cn) { cond_expr_t *cur; unsigned int i; cur = cn->expr; while (cur) { if (cur->bool) cur->bool = state->boolmap[cur->bool - 1]; cur = cur->next; } for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++) cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1]; if (cond_normalize_expr(state->out, cn)) { ERR(state->handle, "Error while normalizing conditional"); return -1; } return 0; } /* copy the nodes in *reverse* order -- the result is that the last * given conditional appears first in the policy, so as to match the * behavior of the upstream compiler */ static int cond_node_copy(expand_state_t * state, cond_node_t * cn) { cond_node_t *new_cond, *tmp; if (cn == NULL) { return 0; } if (cond_node_copy(state, cn->next)) { return -1; } /* If current cond_node_t is of tunable, its effective branch * has been appended to its home decl->avrules list during link * and now we should just skip it. */ if (cn->flags & COND_NODE_FLAGS_TUNABLE) return 0; if (cond_normalize_expr(state->base, cn)) { ERR(state->handle, "Error while normalizing conditional"); return -1; } /* create a new temporary conditional node with the booleans * mapped */ tmp = cond_node_create(state->base, cn); if (!tmp) { ERR(state->handle, "Out of memory"); return -1; } if (cond_node_map_bools(state, tmp)) { cond_node_destroy(tmp); free(tmp); ERR(state->handle, "Error mapping booleans"); return -1; } new_cond = cond_node_search(state->out, state->out->cond_list, tmp); if (!new_cond) { cond_node_destroy(tmp); free(tmp); ERR(state->handle, "Out of memory!"); return -1; } cond_node_destroy(tmp); free(tmp); if (cond_avrule_list_copy (state->out, cn->avtrue_list, &state->out->te_cond_avtab, &new_cond->true_list, &new_cond->false_list, state->typemap, new_cond->cur_state, state)) return -1; if (cond_avrule_list_copy (state->out, cn->avfalse_list, &state->out->te_cond_avtab, &new_cond->false_list, &new_cond->true_list, state->typemap, !new_cond->cur_state, state)) return -1; return 0; } static int context_copy(context_struct_t * dst, context_struct_t * src, expand_state_t * state) { dst->user = state->usermap[src->user - 1]; dst->role = state->rolemap[src->role - 1]; dst->type = state->typemap[src->type - 1]; return mls_context_cpy(dst, src); } static int ocontext_copy_xen(expand_state_t *state) { unsigned int i; ocontext_t *c, *n, *l; for (i = 0; i < OCON_NUM; i++) { l = NULL; for (c = state->base->ocontexts[i]; c; c = c->next) { n = malloc(sizeof(ocontext_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(ocontext_t)); if (l) l->next = n; else state->out->ocontexts[i] = n; l = n; switch (i) { case OCON_XEN_ISID: if (c->context[0].user == 0) { ERR(state->handle, "Missing context for %s initial sid", c->u.name); return -1; } n->sid[0] = c->sid[0]; break; case OCON_XEN_PIRQ: n->u.pirq = c->u.pirq; break; case OCON_XEN_IOPORT: n->u.ioport.low_ioport = c->u.ioport.low_ioport; n->u.ioport.high_ioport = c->u.ioport.high_ioport; break; case OCON_XEN_IOMEM: n->u.iomem.low_iomem = c->u.iomem.low_iomem; n->u.iomem.high_iomem = c->u.iomem.high_iomem; break; case OCON_XEN_PCIDEVICE: n->u.device = c->u.device; break; case OCON_XEN_DEVICETREE: n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } break; default: /* shouldn't get here */ ERR(state->handle, "Unknown ocontext"); return -1; } if (context_copy(&n->context[0], &c->context[0], state)) { ERR(state->handle, "Out of memory!"); return -1; } } } return 0; } static int ocontext_copy_selinux(expand_state_t *state) { unsigned int i, j; ocontext_t *c, *n, *l; for (i = 0; i < OCON_NUM; i++) { l = NULL; for (c = state->base->ocontexts[i]; c; c = c->next) { n = malloc(sizeof(ocontext_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(ocontext_t)); if (l) l->next = n; else state->out->ocontexts[i] = n; l = n; switch (i) { case OCON_ISID: if (c->context[0].user == 0) { ERR(state->handle, "Missing context for %s initial sid", c->u.name); return -1; } n->sid[0] = c->sid[0]; break; case OCON_FS: /* FALLTHROUGH */ case OCON_NETIF: n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } if (context_copy (&n->context[1], &c->context[1], state)) { ERR(state->handle, "Out of memory!"); return -1; } break; case OCON_IBPKEY: n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix; n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey; n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey; break; case OCON_IBENDPORT: n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name); if (!n->u.ibendport.dev_name) { ERR(state->handle, "Out of memory!"); return -1; } n->u.ibendport.port = c->u.ibendport.port; break; case OCON_PORT: n->u.port.protocol = c->u.port.protocol; n->u.port.low_port = c->u.port.low_port; n->u.port.high_port = c->u.port.high_port; break; case OCON_NODE: n->u.node.addr = c->u.node.addr; n->u.node.mask = c->u.node.mask; break; case OCON_FSUSE: n->v.behavior = c->v.behavior; n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } break; case OCON_NODE6: for (j = 0; j < 4; j++) n->u.node6.addr[j] = c->u.node6.addr[j]; for (j = 0; j < 4; j++) n->u.node6.mask[j] = c->u.node6.mask[j]; break; default: /* shouldn't get here */ ERR(state->handle, "Unknown ocontext"); return -1; } if (context_copy(&n->context[0], &c->context[0], state)) { ERR(state->handle, "Out of memory!"); return -1; } } } return 0; } static int ocontext_copy(expand_state_t *state, uint32_t target) { int rc = -1; switch (target) { case SEPOL_TARGET_SELINUX: rc = ocontext_copy_selinux(state); break; case SEPOL_TARGET_XEN: rc = ocontext_copy_xen(state); break; default: ERR(state->handle, "Unknown target"); return -1; } return rc; } static int genfs_copy(expand_state_t * state) { ocontext_t *c, *newc, *l; genfs_t *genfs, *newgenfs, *end; end = NULL; for (genfs = state->base->genfs; genfs; genfs = genfs->next) { newgenfs = malloc(sizeof(genfs_t)); if (!newgenfs) { ERR(state->handle, "Out of memory!"); return -1; } memset(newgenfs, 0, sizeof(genfs_t)); newgenfs->fstype = strdup(genfs->fstype); if (!newgenfs->fstype) { free(newgenfs); ERR(state->handle, "Out of memory!"); return -1; } if (!end) state->out->genfs = newgenfs; else end->next = newgenfs; end = newgenfs; l = NULL; for (c = genfs->head; c; c = c->next) { newc = malloc(sizeof(ocontext_t)); if (!newc) { ERR(state->handle, "Out of memory!"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = strdup(c->u.name); if (!newc->u.name) { ERR(state->handle, "Out of memory!"); free(newc); return -1; } newc->v.sclass = c->v.sclass; context_copy(&newc->context[0], &c->context[0], state); if (l) l->next = newc; else newgenfs->head = newc; l = newc; } } return 0; } static int type_attr_map(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *ptr) { type_datum_t *type; expand_state_t *state = ptr; policydb_t *p = state->out; unsigned int i; ebitmap_node_t *tnode; int value; type = (type_datum_t *) datum; value = type->s.value; if (type->flavor == TYPE_ATTRIB) { if (!(type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE)) { if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) { goto oom; } ebitmap_for_each_bit(&type->types, tnode, i) { if (!ebitmap_node_get_bit(tnode, i)) continue; if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) { goto oom; } } } else { /* Attribute is being expanded, so remove */ if (ebitmap_set_bit(&p->type_attr_map[value - 1], value - 1, 0)) { goto oom; } } } else { if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) { goto oom; } } return 0; oom: ERR(state->handle, "Out of memory!"); return -1; } /* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy. * this should not be called until after all the blocks have been processed and the attributes in target policy * are complete. */ int expand_convert_type_set(policydb_t * p, uint32_t * typemap, type_set_t * set, ebitmap_t * types, unsigned char alwaysexpand) { type_set_t tmpset; type_set_init(&tmpset); if (map_ebitmap(&set->types, &tmpset.types, typemap)) return -1; if (map_ebitmap(&set->negset, &tmpset.negset, typemap)) return -1; tmpset.flags = set->flags; if (type_set_expand(&tmpset, types, p, alwaysexpand)) return -1; type_set_destroy(&tmpset); return 0; } /* Expand a rule into a given avtab - checking for conflicting type * rules. Return 1 on success, 0 if the rule conflicts with something * (and hence was not added), or -1 on error. */ int expand_rule(sepol_handle_t * handle, policydb_t * source_pol, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled) { int retval; ebitmap_t stypes, ttypes; if ((source_rule->specified & AVRULE_NEVERALLOW) || (source_rule->specified & AVRULE_XPERMS_NEVERALLOW)) return 1; ebitmap_init(&stypes); ebitmap_init(&ttypes); if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1)) return -1; if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1)) return -1; retval = expand_rule_helper(handle, source_pol, NULL, source_rule, dest_avtab, cond, other, enabled, &stypes, &ttypes); ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return retval; } /* Expand a role set into an ebitmap containing the roles. * This handles the attribute and flags. * Attribute expansion depends on if the rolemap is available. * During module compile the rolemap is not available, the * possible duplicates of a regular role and the role attribute * the regular role belongs to could be properly handled by * copy_role_trans and copy_role_allow. */ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap) { unsigned int i; ebitmap_node_t *rnode; ebitmap_t mapped_roles, roles; policydb_t *p = out; role_datum_t *role; ebitmap_init(r); if (x->flags & ROLE_STAR) { for (i = 0; i < p->p_roles.nprim; i++) if (ebitmap_set_bit(r, i, 1)) return -1; return 0; } ebitmap_init(&mapped_roles); ebitmap_init(&roles); if (rolemap) { assert(base != NULL); ebitmap_for_each_bit(&x->roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { /* take advantage of p_role_val_to_struct[] * of the base module */ role = base->role_val_to_struct[i]; assert(role != NULL); if (role->flavor == ROLE_ATTRIB) { if (ebitmap_union(&roles, &role->roles)) goto bad; } else { if (ebitmap_set_bit(&roles, i, 1)) goto bad; } } } if (map_ebitmap(&roles, &mapped_roles, rolemap)) goto bad; } else { if (ebitmap_cpy(&mapped_roles, &x->roles)) goto bad; } ebitmap_for_each_bit(&mapped_roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { if (ebitmap_set_bit(r, i, 1)) goto bad; } } ebitmap_destroy(&mapped_roles); ebitmap_destroy(&roles); /* if role is to be complimented, invert the entire bitmap here */ if (x->flags & ROLE_COMP) { for (i = 0; i < ebitmap_length(r); i++) { if (ebitmap_get_bit(r, i)) { if (ebitmap_set_bit(r, i, 0)) return -1; } else { if (ebitmap_set_bit(r, i, 1)) return -1; } } } return 0; bad: ebitmap_destroy(&mapped_roles); ebitmap_destroy(&roles); return -1; } /* Expand a type set into an ebitmap containing the types. This * handles the negset, attributes, and flags. * Attribute expansion depends on several factors: * - if alwaysexpand is 1, then they will be expanded, * - if the type set has a negset or flags, then they will be expanded, * - otherwise, they will not be expanded. */ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, unsigned char alwaysexpand) { unsigned int i; ebitmap_t types, neg_types; ebitmap_node_t *tnode; unsigned char expand = alwaysexpand || ebitmap_length(&set->negset) || set->flags; type_datum_t *type; int rc =-1; ebitmap_init(&types); ebitmap_init(t); /* First go through the types and OR all the attributes to types */ ebitmap_for_each_bit(&set->types, tnode, i) { if (!ebitmap_node_get_bit(tnode, i)) continue; /* * invalid policies might have more types set in the ebitmap than * what's available in the type_val_to_struct mapping */ if (i >= p->p_types.nprim) goto err_types; type = p->type_val_to_struct[i]; if (!type) { goto err_types; } if (type->flavor == TYPE_ATTRIB && (expand || (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE))) { if (ebitmap_union(&types, &type->types)) { goto err_types; } } else { if (ebitmap_set_bit(&types, i, 1)) { goto err_types; } } } /* Now do the same thing for negset */ ebitmap_init(&neg_types); ebitmap_for_each_bit(&set->negset, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { if (ebitmap_union (&neg_types, &p->type_val_to_struct[i]->types)) { goto err_neg; } } else { if (ebitmap_set_bit(&neg_types, i, 1)) { goto err_neg; } } } } if (set->flags & TYPE_STAR) { /* set all types not in neg_types */ for (i = 0; i < p->p_types.nprim; i++) { if (ebitmap_get_bit(&neg_types, i)) continue; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) continue; if (ebitmap_set_bit(t, i, 1)) goto err_neg; } goto out; } ebitmap_for_each_bit(&types, tnode, i) { if (ebitmap_node_get_bit(tnode, i) && (!ebitmap_get_bit(&neg_types, i))) if (ebitmap_set_bit(t, i, 1)) goto err_neg; } if (set->flags & TYPE_COMP) { for (i = 0; i < p->p_types.nprim; i++) { if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { assert(!ebitmap_get_bit(t, i)); continue; } if (ebitmap_get_bit(t, i)) { if (ebitmap_set_bit(t, i, 0)) goto err_neg; } else { if (ebitmap_set_bit(t, i, 1)) goto err_neg; } } } out: rc = 0; err_neg: ebitmap_destroy(&neg_types); err_types: ebitmap_destroy(&types); return rc; } static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, avrule_t * source_rule) { ebitmap_t stypes, ttypes; avrule_t *avrule; class_perm_node_t *cur_perm, *new_perm, *tail_perm; av_extended_perms_t *xperms = NULL; ebitmap_init(&stypes); ebitmap_init(&ttypes); if (expand_convert_type_set (dest_pol, typemap, &source_rule->stypes, &stypes, 1)) return -1; if (expand_convert_type_set (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1)) return -1; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) return -1; avrule_init(avrule); avrule->specified = source_rule->specified; avrule->line = source_rule->line; avrule->flags = source_rule->flags; avrule->source_line = source_rule->source_line; if (source_rule->source_filename) { avrule->source_filename = strdup(source_rule->source_filename); if (!avrule->source_filename) goto err; } if (ebitmap_cpy(&avrule->stypes.types, &stypes)) goto err; if (ebitmap_cpy(&avrule->ttypes.types, &ttypes)) goto err; cur_perm = source_rule->perms; tail_perm = NULL; while (cur_perm) { new_perm = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!new_perm) goto err; class_perm_node_init(new_perm); new_perm->tclass = cur_perm->tclass; assert(new_perm->tclass); /* once we have modules with permissions we'll need to map the permissions (and classes) */ new_perm->data = cur_perm->data; if (!avrule->perms) avrule->perms = new_perm; if (tail_perm) tail_perm->next = new_perm; tail_perm = new_perm; cur_perm = cur_perm->next; } /* copy over extended permissions */ if (source_rule->xperms) { xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) goto err; memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t)); avrule->xperms = xperms; } /* just prepend the avrule to the first branch; it'll never be written to disk */ if (!dest_pol->global->branch_list->avrules) dest_pol->global->branch_list->avrules = avrule; else { avrule->next = dest_pol->global->branch_list->avrules; dest_pol->global->branch_list->avrules = avrule; } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return 0; err: ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); ebitmap_destroy(&avrule->stypes.types); ebitmap_destroy(&avrule->ttypes.types); cur_perm = avrule->perms; while (cur_perm) { tail_perm = cur_perm->next; free(cur_perm); cur_perm = tail_perm; } free(xperms); free(avrule); return -1; } /* * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow * rules are copied or expanded as per the settings in the state object; all * other AV rules are expanded. If neverallow rules are expanded, they are not * copied, otherwise they are copied for later use by the assertion checker. */ static int copy_and_expand_avrule_block(expand_state_t * state) { avrule_block_t *curblock = state->base->global; avrule_block_t *prevblock; int retval = -1; if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) { ERR(state->handle, "Out of Memory!"); return -1; } if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) { ERR(state->handle, "Out of Memory!"); return -1; } while (curblock) { avrule_decl_t *decl = curblock->enabled; avrule_t *cur_avrule; if (decl == NULL) { /* nothing was enabled within this block */ goto cont; } /* copy role allows and role trans */ if (copy_role_allows(state, decl->role_allow_rules) != 0 || copy_role_trans(state, decl->role_tr_rules) != 0) { goto cleanup; } if (expand_filename_trans(state, decl->filename_trans_rules)) goto cleanup; /* expand the range transition rules */ if (expand_range_trans(state, decl->range_tr_rules)) goto cleanup; /* copy rules */ cur_avrule = decl->avrules; while (cur_avrule != NULL) { if (!(state->expand_neverallow) && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) { /* copy this over directly so that assertions are checked later */ if (copy_neverallow (state->out, state->typemap, cur_avrule)) ERR(state->handle, "Error while copying neverallow."); } else { if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) state->out->unsupported_format = 1; if (convert_and_expand_rule (state->handle, state->out, state->typemap, cur_avrule, &state->out->te_avtab, NULL, NULL, 0, state->expand_neverallow) != EXPAND_RULE_SUCCESS) { goto cleanup; } } cur_avrule = cur_avrule->next; } /* copy conditional rules */ if (cond_node_copy(state, decl->cond_list)) goto cleanup; cont: prevblock = curblock; curblock = curblock->next; if (state->handle && state->handle->expand_consume_base) { /* set base top avrule block in case there * is an error condition and the policy needs * to be destroyed */ state->base->global = curblock; avrule_block_destroy(prevblock); } } retval = 0; cleanup: return retval; } /* * This function allows external users of the library (such as setools) to * expand only the avrules and optionally perform expansion of neverallow rules * or expand into the same policy for analysis purposes. */ int expand_module_avrules(sepol_handle_t * handle, policydb_t * base, policydb_t * out, uint32_t * typemap, uint32_t * boolmap, uint32_t * rolemap, uint32_t * usermap, int verbose, int expand_neverallow) { expand_state_t state; expand_state_init(&state); state.base = base; state.out = out; state.typemap = typemap; state.boolmap = boolmap; state.rolemap = rolemap; state.usermap = usermap; state.handle = handle; state.verbose = verbose; state.expand_neverallow = expand_neverallow; return copy_and_expand_avrule_block(&state); } static void discard_tunables(sepol_handle_t *sh, policydb_t *pol) { avrule_block_t *block; avrule_decl_t *decl; cond_node_t *cur_node; cond_expr_t *cur_expr; int cur_state, preserve_tunables = 0; avrule_t *tail, *to_be_appended; if (sh && sh->preserve_tunables) preserve_tunables = 1; /* Iterate through all cond_node of all enabled decls, if a cond_node * is about tunable, calculate its state value and concatenate one of * its avrule list to the current decl->avrules list. On the other * hand, the disabled unused branch of a tunable would be discarded. * * Note, such tunable cond_node would be skipped over in expansion, * so we won't have to worry about removing it from decl->cond_list * here :-) * * If tunables are requested to be preserved then they would be * "transformed" as booleans by having their TUNABLE flag cleared. */ for (block = pol->global; block != NULL; block = block->next) { decl = block->enabled; if (decl == NULL || decl->enabled == 0) continue; tail = decl->avrules; while (tail && tail->next) tail = tail->next; for (cur_node = decl->cond_list; cur_node != NULL; cur_node = cur_node->next) { int booleans, tunables, i; cond_bool_datum_t *booldatum; cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH]; booleans = tunables = 0; memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH); for (cur_expr = cur_node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { if (cur_expr->expr_type != COND_BOOL) continue; booldatum = pol->bool_val_to_struct[cur_expr->bool - 1]; if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE) tmp[tunables++] = booldatum; else booleans++; } /* bool_copy_callback() at link phase has ensured * that no mixture of tunables and booleans in one * expression. However, this would be broken by the * request to preserve tunables */ if (!preserve_tunables) assert(!(booleans && tunables)); if (booleans || preserve_tunables) { cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE; if (tunables) { for (i = 0; i < tunables; i++) tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE; } } else { cur_node->flags |= COND_NODE_FLAGS_TUNABLE; cur_state = cond_evaluate_expr(pol, cur_node->expr); if (cur_state == -1) { printf("Expression result was " "undefined, skipping all" "rules\n"); continue; } to_be_appended = (cur_state == 1) ? cur_node->avtrue_list : cur_node->avfalse_list; if (tail) tail->next = to_be_appended; else tail = decl->avrules = to_be_appended; /* Now that the effective branch has been * appended, neutralize its original pointer */ if (cur_state == 1) cur_node->avtrue_list = NULL; else cur_node->avfalse_list = NULL; /* Update the tail of decl->avrules for * further concatenation */ while (tail && tail->next) tail = tail->next; } } } } /* Linking should always be done before calling expand, even if * there is only a base since all optionals are dealt with at link time * the base passed in should be indexed and avrule blocks should be * enabled. */ int expand_module(sepol_handle_t * handle, policydb_t * base, policydb_t * out, int verbose, int check) { int retval = -1; unsigned int i; expand_state_t state; avrule_block_t *curblock; /* Append tunable's avtrue_list or avfalse_list to the avrules list * of its home decl depending on its state value, so that the effect * rules of a tunable would be added to te_avtab permanently. Whereas * the disabled unused branch would be discarded. * * Originally this function is called at the very end of link phase, * however, we need to keep the linked policy intact for analysis * purpose. */ discard_tunables(handle, base); expand_state_init(&state); state.verbose = verbose; state.typemap = NULL; state.base = base; state.out = out; state.handle = handle; if (base->policy_type != POLICY_BASE) { ERR(handle, "Target of expand was not a base policy."); return -1; } state.out->policy_type = POLICY_KERN; state.out->policyvers = POLICYDB_VERSION_MAX; /* Copy mls state from base to out */ out->mls = base->mls; out->handle_unknown = base->handle_unknown; /* Copy target from base to out */ out->target_platform = base->target_platform; /* Copy policy capabilities */ if (ebitmap_cpy(&out->policycaps, &base->policycaps)) { ERR(handle, "Out of memory!"); goto cleanup; } if ((state.typemap = (uint32_t *) calloc(state.base->p_types.nprim, sizeof(uint32_t))) == NULL) { ERR(handle, "Out of memory!"); goto cleanup; } state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t)); if (!state.boolmap) { ERR(handle, "Out of memory!"); goto cleanup; } state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t)); if (!state.rolemap) { ERR(handle, "Out of memory!"); goto cleanup; } state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t)); if (!state.usermap) { ERR(handle, "Out of memory!"); goto cleanup; } /* order is important - types must be first */ /* copy types */ if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) { goto cleanup; } /* convert attribute type sets */ if (hashtab_map (state.base->p_types.table, attr_convert_callback, &state)) { goto cleanup; } /* copy commons */ if (hashtab_map (state.base->p_commons.table, common_copy_callback, &state)) { goto cleanup; } /* copy classes, note, this does not copy constraints, constraints can't be * copied until after all the blocks have been processed and attributes are complete */ if (hashtab_map (state.base->p_classes.table, class_copy_callback, &state)) { goto cleanup; } /* copy type bounds */ if (hashtab_map(state.base->p_types.table, type_bounds_copy_callback, &state)) goto cleanup; /* copy aliases */ if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state)) goto cleanup; /* index here so that type indexes are available for role_copy_callback */ if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* copy roles */ if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_roles.table, role_bounds_copy_callback, &state)) goto cleanup; /* escalate the type_set_t in a role attribute to all regular roles * that belongs to it. */ if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state)) goto cleanup; /* copy MLS's sensitivity level and categories - this needs to be done * before expanding users (they need to be indexed too) */ if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state)) goto cleanup; if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* copy users */ if (hashtab_map(state.base->p_users.table, user_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_users.table, user_bounds_copy_callback, &state)) goto cleanup; /* copy bools */ if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state)) goto cleanup; if (policydb_index_classes(out)) { ERR(handle, "Error while indexing out classes"); goto cleanup; } if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* loop through all decls and union attributes, roles, users */ for (curblock = state.base->global; curblock != NULL; curblock = curblock->next) { avrule_decl_t *decl = curblock->enabled; if (decl == NULL) { /* nothing was enabled within this block */ continue; } /* convert attribute type sets */ if (hashtab_map (decl->p_types.table, attr_convert_callback, &state)) { goto cleanup; } /* copy roles */ if (hashtab_map (decl->p_roles.table, role_copy_callback, &state)) goto cleanup; /* copy users */ if (hashtab_map (decl->p_users.table, user_copy_callback, &state)) goto cleanup; } /* remap role dominates bitmaps */ if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) { goto cleanup; } if (copy_and_expand_avrule_block(&state) < 0) { ERR(handle, "Error during expand"); goto cleanup; } /* copy constraints */ if (hashtab_map (state.base->p_classes.table, constraint_copy_callback, &state)) { goto cleanup; } cond_optimize_lists(state.out->cond_list); if (evaluate_conds(state.out)) goto cleanup; /* copy ocontexts */ if (ocontext_copy(&state, out->target_platform)) goto cleanup; /* copy genfs */ if (genfs_copy(&state)) goto cleanup; /* Build the type<->attribute maps and remove attributes. */ state.out->attr_type_map = malloc(state.out->p_types.nprim * sizeof(ebitmap_t)); state.out->type_attr_map = malloc(state.out->p_types.nprim * sizeof(ebitmap_t)); if (!state.out->attr_type_map || !state.out->type_attr_map) { ERR(handle, "Out of memory!"); goto cleanup; } for (i = 0; i < state.out->p_types.nprim; i++) { ebitmap_init(&state.out->type_attr_map[i]); ebitmap_init(&state.out->attr_type_map[i]); /* add the type itself as the degenerate case */ if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) { ERR(handle, "Out of memory!"); goto cleanup; } } if (hashtab_map(state.out->p_types.table, type_attr_map, &state)) goto cleanup; if (check) { if (hierarchy_check_constraints(handle, state.out)) goto cleanup; if (check_assertions (handle, state.out, state.out->global->branch_list->avrules)) goto cleanup; } retval = 0; cleanup: free(state.typemap); free(state.boolmap); free(state.rolemap); free(state.usermap); return retval; } static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d) { avtab_ptr_t node; avtab_datum_t *avd; avtab_extended_perms_t *xperms; unsigned int i; unsigned int match = 0; if (k->specified & AVTAB_XPERMS) { /* * AVTAB_XPERMS entries are not necessarily unique. * find node with matching xperms */ node = avtab_search_node(a, k); while (node) { if ((node->datum.xperms->specified == d->xperms->specified) && (node->datum.xperms->driver == d->xperms->driver)) { match = 1; break; } node = avtab_search_node_next(node, k->specified); } if (!match) node = NULL; } else { node = avtab_search_node(a, k); } if (!node || ((k->specified & AVTAB_ENABLED) != (node->key.specified & AVTAB_ENABLED))) { node = avtab_insert_nonunique(a, k, d); if (!node) { ERR(NULL, "Out of memory!"); return -1; } return 0; } avd = &node->datum; xperms = node->datum.xperms; switch (k->specified & ~AVTAB_ENABLED) { case AVTAB_ALLOWED: case AVTAB_AUDITALLOW: avd->data |= d->data; break; case AVTAB_AUDITDENY: avd->data &= d->data; break; case AVTAB_XPERMS_ALLOWED: case AVTAB_XPERMS_AUDITALLOW: case AVTAB_XPERMS_DONTAUDIT: for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) xperms->perms[i] |= d->xperms->perms[i]; break; default: ERR(NULL, "Type conflict!"); return -1; } return 0; } struct expand_avtab_data { avtab_t *expa; policydb_t *p; }; static int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args) { struct expand_avtab_data *ptr = args; avtab_t *expa = ptr->expa; policydb_t *p = ptr->p; type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; ebitmap_node_t *snode, *tnode; unsigned int i, j; avtab_key_t newkey; int rc; newkey.target_class = k->target_class; newkey.specified = k->specified; if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { /* Both are individual types, no expansion required. */ return expand_avtab_insert(expa, k, d); } if (stype && stype->flavor != TYPE_ATTRIB) { /* Source is an individual type, target is an attribute. */ newkey.source_type = k->source_type; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; newkey.target_type = j + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } return 0; } if (ttype && ttype->flavor != TYPE_ATTRIB) { /* Target is an individual type, source is an attribute. */ newkey.target_type = k->target_type; ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; newkey.source_type = i + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } return 0; } /* Both source and target type are attributes. */ ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; newkey.source_type = i + 1; newkey.target_type = j + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } } return 0; } int expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa) { struct expand_avtab_data data; if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { ERR(NULL, "Out of memory!"); return -1; } data.expa = expa; data.p = p; return avtab_map(a, expand_avtab_node, &data); } static int expand_cond_insert(cond_av_list_t ** l, avtab_t * expa, avtab_key_t * k, avtab_datum_t * d) { avtab_ptr_t node; avtab_datum_t *avd; cond_av_list_t *nl; node = avtab_search_node(expa, k); if (!node || (k->specified & AVTAB_ENABLED) != (node->key.specified & AVTAB_ENABLED)) { node = avtab_insert_nonunique(expa, k, d); if (!node) { ERR(NULL, "Out of memory!"); return -1; } node->parse_context = (void *)1; nl = (cond_av_list_t *) malloc(sizeof(*nl)); if (!nl) { ERR(NULL, "Out of memory!"); return -1; } memset(nl, 0, sizeof(*nl)); nl->node = node; nl->next = *l; *l = nl; return 0; } avd = &node->datum; switch (k->specified & ~AVTAB_ENABLED) { case AVTAB_ALLOWED: case AVTAB_AUDITALLOW: avd->data |= d->data; break; case AVTAB_AUDITDENY: avd->data &= d->data; break; default: ERR(NULL, "Type conflict!"); return -1; } return 0; } int expand_cond_av_node(policydb_t * p, avtab_ptr_t node, cond_av_list_t ** newl, avtab_t * expa) { avtab_key_t *k = &node->key; avtab_datum_t *d = &node->datum; type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; ebitmap_node_t *snode, *tnode; unsigned int i, j; avtab_key_t newkey; int rc; newkey.target_class = k->target_class; newkey.specified = k->specified; if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { /* Both are individual types, no expansion required. */ return expand_cond_insert(newl, expa, k, d); } if (stype && stype->flavor != TYPE_ATTRIB) { /* Source is an individual type, target is an attribute. */ newkey.source_type = k->source_type; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; newkey.target_type = j + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } return 0; } if (ttype && ttype->flavor != TYPE_ATTRIB) { /* Target is an individual type, source is an attribute. */ newkey.target_type = k->target_type; ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; newkey.source_type = i + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } return 0; } /* Both source and target type are attributes. */ ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; newkey.source_type = i + 1; newkey.target_type = j + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } } return 0; } int expand_cond_av_list(policydb_t * p, cond_av_list_t * l, cond_av_list_t ** newl, avtab_t * expa) { cond_av_list_t *cur; avtab_ptr_t node; int rc; if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { ERR(NULL, "Out of memory!"); return -1; } *newl = NULL; for (cur = l; cur; cur = cur->next) { node = cur->node; rc = expand_cond_av_node(p, node, newl, expa); if (rc) return rc; } return 0; } libsepol/src/genbools.c0100644 0000000 0000000 00000012713 13756670065 014204 0ustar000000000 0000000 #include #include #include #include #include #include #include "debug.h" #include "private.h" #include "dso.h" /* -- Deprecated -- */ static char *strtrim(char *dest, char *source, int size) { int i = 0; char *ptr = source; i = 0; while (isspace(*ptr) && i < size) { ptr++; i++; } strncpy(dest, ptr, size); for (i = strlen(dest) - 1; i > 0; i--) { if (!isspace(dest[i])) break; } dest[i + 1] = '\0'; return dest; } static int process_boolean(char *buffer, char *name, int namesize, int *val) { char name1[BUFSIZ]; char *ptr = NULL; char *tok; /* Skip spaces */ while (isspace(buffer[0])) buffer++; /* Ignore comments */ if (buffer[0] == '#') return 0; tok = strtok_r(buffer, "=", &ptr); if (!tok) { ERR(NULL, "illegal boolean definition %s", buffer); return -1; } strncpy(name1, tok, BUFSIZ - 1); strtrim(name, name1, namesize - 1); tok = strtok_r(NULL, "\0", &ptr); if (!tok) { ERR(NULL, "illegal boolean definition %s=%s", name, buffer); return -1; } while (isspace(*tok)) tok++; *val = -1; if (isdigit(tok[0])) *val = atoi(tok); else if (!strncasecmp(tok, "true", sizeof("true") - 1)) *val = 1; else if (!strncasecmp(tok, "false", sizeof("false") - 1)) *val = 0; if (*val != 0 && *val != 1) { ERR(NULL, "illegal value for boolean %s=%s", name, tok); return -1; } return 1; } static int load_booleans(struct policydb *policydb, const char *path, int *changesp) { FILE *boolf; char *buffer = NULL; char localbools[BUFSIZ]; char name[BUFSIZ]; int val; int errors = 0, changes = 0; struct cond_bool_datum *datum; boolf = fopen(path, "r"); if (boolf == NULL) goto localbool; #ifdef __APPLE__ if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { ERR(NULL, "out of memory"); return -1; } while(fgets(buffer, 255, boolf) != NULL) { #else size_t size = 0; while (getline(&buffer, &size, boolf) > 0) { #endif int ret = process_boolean(buffer, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) { datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(NULL, "unknown boolean %s", name); errors++; continue; } if (datum->state != val) { datum->state = val; changes++; } } } fclose(boolf); localbool: snprintf(localbools, sizeof(localbools), "%s.local", path); boolf = fopen(localbools, "r"); if (boolf != NULL) { #ifdef __APPLE__ while(fgets(buffer, 255, boolf) != NULL) { #else while (getline(&buffer, &size, boolf) > 0) { #endif int ret = process_boolean(buffer, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) { datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(NULL, "unknown boolean %s", name); errors++; continue; } if (datum->state != val) { datum->state = val; changes++; } } } fclose(boolf); } free(buffer); if (errors) errno = EINVAL; *changesp = changes; return errors ? -1 : 0; } int sepol_genbools(void *data, size_t len, const char *booleans) { struct policydb policydb; struct policy_file pf; int rc, changes = 0; if (policydb_init(&policydb)) goto err; if (policydb_from_image(NULL, data, len, &policydb) < 0) goto err; if (load_booleans(&policydb, booleans, &changes) < 0) { WARN(NULL, "error while reading %s", booleans); } if (!changes) goto out; if (evaluate_conds(&policydb) < 0) { ERR(NULL, "error while re-evaluating conditionals"); errno = EINVAL; goto err_destroy; } policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; rc = policydb_write(&policydb, &pf); if (rc) { ERR(NULL, "unable to write new binary policy image"); errno = EINVAL; goto err_destroy; } out: policydb_destroy(&policydb); return 0; err_destroy: policydb_destroy(&policydb); err: return -1; } int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans) { int rc, changes = 0; rc = load_booleans(policydb, booleans, &changes); if (!rc && changes) rc = evaluate_conds(policydb); if (rc) errno = EINVAL; return rc; } /* -- End Deprecated -- */ int sepol_genbools_array(void *data, size_t len, char **names, int *values, int nel) { struct policydb policydb; struct policy_file pf; int rc, i, errors = 0; struct cond_bool_datum *datum; /* Create policy database from image */ if (policydb_init(&policydb)) goto err; if (policydb_from_image(NULL, data, len, &policydb) < 0) goto err; for (i = 0; i < nel; i++) { datum = hashtab_search(policydb.p_bools.table, names[i]); if (!datum) { ERR(NULL, "boolean %s no longer in policy", names[i]); errors++; continue; } if (values[i] != 0 && values[i] != 1) { ERR(NULL, "illegal value %d for boolean %s", values[i], names[i]); errors++; continue; } datum->state = values[i]; } if (evaluate_conds(&policydb) < 0) { ERR(NULL, "error while re-evaluating conditionals"); errno = EINVAL; goto err_destroy; } policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; rc = policydb_write(&policydb, &pf); if (rc) { ERR(NULL, "unable to write binary policy"); errno = EINVAL; goto err_destroy; } if (errors) { errno = EINVAL; goto err_destroy; } policydb_destroy(&policydb); return 0; err_destroy: policydb_destroy(&policydb); err: return -1; } libsepol/src/genusers.c0100644 0000000 0000000 00000014712 13756670065 014230 0ustar000000000 0000000 #include #include #include #include #include #include #ifndef __APPLE__ #include #endif #include #include "debug.h" #include "private.h" #include "dso.h" #include "mls.h" /* -- Deprecated -- */ void sepol_set_delusers(int on __attribute((unused))) { WARN(NULL, "Deprecated interface"); } #undef BADLINE #define BADLINE() { \ ERR(NULL, "invalid entry %s (%s:%u)", \ buffer, path, lineno); \ continue; \ } static int load_users(struct policydb *policydb, const char *path) { FILE *fp; char *buffer = NULL, *p, *q, oldc; ssize_t nread; unsigned lineno = 0, islist = 0, bit; user_datum_t *usrdatum; role_datum_t *roldatum; ebitmap_node_t *rnode; fp = fopen(path, "r"); if (fp == NULL) return -1; #ifdef __APPLE__ if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { ERR(NULL, "out of memory"); return -1; } while(fgets(buffer, 255, fp) != NULL) { nread = strlen(buffer); #else size_t len = 0; __fsetlocking(fp, FSETLOCKING_BYCALLER); while ((nread = getline(&buffer, &len, fp)) > 0) { #endif lineno++; if (buffer[nread - 1] == '\n') buffer[nread - 1] = 0; p = buffer; while (*p && isspace(*p)) p++; if (!(*p) || *p == '#') continue; if (strncasecmp(p, "user", 4)) BADLINE(); p += 4; if (!isspace(*p)) BADLINE(); while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); q = p; while (*p && !isspace(*p)) p++; if (!(*p)) BADLINE(); *p++ = 0; usrdatum = hashtab_search(policydb->p_users.table, q); if (usrdatum) { /* Replacing an existing user definition. */ ebitmap_destroy(&usrdatum->roles.roles); ebitmap_init(&usrdatum->roles.roles); } else { char *id = strdup(q); if (!id) { ERR(NULL, "out of memory"); free(buffer); fclose(fp); return -1; } /* Adding a new user definition. */ usrdatum = malloc(sizeof(user_datum_t)); if (!usrdatum) { ERR(NULL, "out of memory"); free(buffer); free(id); fclose(fp); return -1; } user_datum_init(usrdatum); usrdatum->s.value = ++policydb->p_users.nprim; if (hashtab_insert(policydb->p_users.table, id, (hashtab_datum_t) usrdatum)) { ERR(NULL, "out of memory"); free(buffer); free(id); user_datum_destroy(usrdatum); free(usrdatum); fclose(fp); return -1; } } while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); if (strncasecmp(p, "roles", 5)) BADLINE(); p += 5; if (!isspace(*p)) BADLINE(); while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); if (*p == '{') { islist = 1; p++; } else islist = 0; oldc = 0; do { while (*p && isspace(*p)) p++; if (!(*p)) break; q = p; while (*p && *p != ';' && *p != '}' && !isspace(*p)) p++; if (!(*p)) break; if (*p == '}') islist = 0; oldc = *p; *p++ = 0; if (!q[0]) break; roldatum = hashtab_search(policydb->p_roles.table, q); if (!roldatum) { ERR(NULL, "undefined role %s (%s:%u)", q, path, lineno); continue; } /* Set the role and every role it dominates */ ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) { if (ebitmap_node_get_bit(rnode, bit)) if (ebitmap_set_bit (&usrdatum->roles.roles, bit, 1)) { ERR(NULL, "out of memory"); free(buffer); fclose(fp); return -1; } } } while (islist); if (oldc == 0) BADLINE(); if (policydb->mls) { context_struct_t context; char *scontext, *r, *s; while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); if (strncasecmp(p, "level", 5)) BADLINE(); p += 5; if (!isspace(*p)) BADLINE(); while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); q = p; while (*p && (!isspace(*p) || strncasecmp(p + 1, "range", 5))) p++; if (!(*p) || p == q) BADLINE(); *p = 0; p++; scontext = malloc(p - q); if (!scontext) { ERR(NULL, "out of memory"); free(buffer); fclose(fp); return -1; } r = scontext; s = q; while (*s) { if (!isspace(*s)) *r++ = *s; s++; } *r = 0; r = scontext; context_init(&context); if (mls_context_to_sid(policydb, oldc, &r, &context) < 0) { ERR(NULL, "invalid level %s (%s:%u)", scontext, path, lineno); free(scontext); continue; } free(scontext); memcpy(&usrdatum->dfltlevel, &context.range.level[0], sizeof(usrdatum->dfltlevel)); if (strncasecmp(p, "range", 5)) BADLINE(); p += 5; if (!isspace(*p)) BADLINE(); while (*p && isspace(*p)) p++; if (!(*p)) BADLINE(); q = p; while (*p && *p != ';') p++; if (!(*p)) BADLINE(); *p++ = 0; scontext = malloc(p - q); if (!scontext) { ERR(NULL, "out of memory"); free(buffer); fclose(fp); return -1; } r = scontext; s = q; while (*s) { if (!isspace(*s)) *r++ = *s; s++; } *r = 0; r = scontext; context_init(&context); if (mls_context_to_sid(policydb, oldc, &r, &context) < 0) { ERR(NULL, "invalid range %s (%s:%u)", scontext, path, lineno); free(scontext); continue; } free(scontext); memcpy(&usrdatum->range, &context.range, sizeof(usrdatum->range)); } } free(buffer); fclose(fp); return 0; } int sepol_genusers(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) { struct policydb policydb; char path[PATH_MAX]; /* Construct policy database */ if (policydb_init(&policydb)) goto err; if (policydb_from_image(NULL, data, len, &policydb) < 0) goto err; /* Load locally defined users. */ snprintf(path, sizeof path, "%s/local.users", usersdir); if (load_users(&policydb, path) < 0) goto err_destroy; /* Write policy database */ if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0) goto err_destroy; policydb_destroy(&policydb); return 0; err_destroy: policydb_destroy(&policydb); err: return -1; } int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir) { char path[PATH_MAX]; /* Load locally defined users. */ snprintf(path, sizeof path, "%s/local.users", usersdir); if (load_users(policydb, path) < 0) { ERR(NULL, "unable to load local.users: %s", strerror(errno)); return -1; } if (policydb_reindex_users(policydb) < 0) { ERR(NULL, "unable to reindex users: %s", strerror(errno)); return -1; } return 0; } /* -- End Deprecated -- */ libsepol/src/handle.c0100644 0000000 0000000 00000002331 13756670065 013622 0ustar000000000 0000000 #include #include #include "handle.h" #include "debug.h" sepol_handle_t *sepol_handle_create(void) { sepol_handle_t *sh = malloc(sizeof(sepol_handle_t)); if (sh == NULL) return NULL; /* Set callback */ sh->msg_callback = sepol_msg_default_handler; sh->msg_callback_arg = NULL; /* by default do not disable dontaudits */ sh->disable_dontaudit = 0; sh->expand_consume_base = 0; /* by default needless unused branch of tunables would be discarded */ sh->preserve_tunables = 0; return sh; } int sepol_get_preserve_tunables(sepol_handle_t *sh) { assert(sh != NULL); return sh->preserve_tunables; } void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables) { assert(sh !=NULL); sh->preserve_tunables = preserve_tunables; } int sepol_get_disable_dontaudit(sepol_handle_t *sh) { assert(sh !=NULL); return sh->disable_dontaudit; } void sepol_set_disable_dontaudit(sepol_handle_t * sh, int disable_dontaudit) { assert(sh !=NULL); sh->disable_dontaudit = disable_dontaudit; } void sepol_set_expand_consume_base(sepol_handle_t *sh, int consume_base) { assert(sh != NULL); sh->expand_consume_base = consume_base; } void sepol_handle_destroy(sepol_handle_t * sh) { free(sh); } libsepol/src/handle.h0100644 0000000 0000000 00000000730 13756670065 013630 0ustar000000000 0000000 #ifndef _SEPOL_INTERNAL_HANDLE_H_ #define _SEPOL_INTERNAL_HANDLE_H_ #include struct sepol_handle { /* Error handling */ int msg_level; const char *msg_channel; const char *msg_fname; #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...); void *msg_callback_arg; int disable_dontaudit; int expand_consume_base; int preserve_tunables; }; #endif libsepol/src/hashtab.c0100644 0000000 0000000 00000014463 13756670065 014012 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated : Karl MacMillan * * Copyright (C) 2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the hash table type. */ #include #include #include hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size) { hashtab_t p; unsigned int i; p = (hashtab_t) malloc(sizeof(hashtab_val_t)); if (p == NULL) return p; memset(p, 0, sizeof(hashtab_val_t)); p->size = size; p->nel = 0; p->hash_value = hash_value; p->keycmp = keycmp; p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size); if (p->htable == NULL) { free(p); return NULL; } for (i = 0; i < size; i++) p->htable[i] = (hashtab_ptr_t) NULL; return p; } int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) { int hvalue; hashtab_ptr_t prev, cur, newnode; if (!h) return SEPOL_ENOMEM; hvalue = h->hash_value(h, key); prev = NULL; cur = h->htable[hvalue]; while (cur && h->keycmp(h, key, cur->key) > 0) { prev = cur; cur = cur->next; } if (cur && (h->keycmp(h, key, cur->key) == 0)) return SEPOL_EEXIST; newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) return SEPOL_ENOMEM; memset(newnode, 0, sizeof(struct hashtab_node)); newnode->key = key; newnode->datum = datum; if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } h->nel++; return SEPOL_OK; } int hashtab_remove(hashtab_t h, hashtab_key_t key, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { int hvalue; hashtab_ptr_t cur, last; if (!h) return SEPOL_ENOENT; hvalue = h->hash_value(h, key); last = NULL; cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { last = cur; cur = cur->next; } if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) return SEPOL_ENOENT; if (last == NULL) h->htable[hvalue] = cur->next; else last->next = cur->next; if (destroy) destroy(cur->key, cur->datum, args); free(cur); h->nel--; return SEPOL_OK; } int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { int hvalue; hashtab_ptr_t prev, cur, newnode; if (!h) return SEPOL_ENOMEM; hvalue = h->hash_value(h, key); prev = NULL; cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { prev = cur; cur = cur->next; } if (cur && (h->keycmp(h, key, cur->key) == 0)) { if (destroy) destroy(cur->key, cur->datum, args); cur->key = key; cur->datum = datum; } else { newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) return SEPOL_ENOMEM; memset(newnode, 0, sizeof(struct hashtab_node)); newnode->key = key; newnode->datum = datum; if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } } return SEPOL_OK; } hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) { int hvalue; hashtab_ptr_t cur; if (!h) return NULL; hvalue = h->hash_value(h, key); cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) cur = cur->next; if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) return NULL; return cur->datum; } void hashtab_destroy(hashtab_t h) { unsigned int i; hashtab_ptr_t cur, temp; if (!h) return; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; free(temp); } h->htable[i] = NULL; } free(h->htable); h->htable = NULL; free(h); } int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int i, ret; hashtab_ptr_t cur; if (!h) return SEPOL_OK; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { ret = apply(cur->key, cur->datum, args); if (ret) return ret; cur = cur->next; } } return SEPOL_OK; } void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int i; int ret; hashtab_ptr_t last, cur, temp; if (!h) return; for (i = 0; i < h->size; i++) { last = NULL; cur = h->htable[i]; while (cur != NULL) { ret = apply(cur->key, cur->datum, args); if (ret) { if (last) { last->next = cur->next; } else { h->htable[i] = cur->next; } temp = cur; cur = cur->next; if (destroy) destroy(temp->key, temp->datum, args); free(temp); h->nel--; } else { last = cur; cur = cur->next; } } } return; } void hashtab_hash_eval(hashtab_t h, char *tag) { unsigned int i; int chain_len, slots_used, max_chain_len; hashtab_ptr_t cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < h->size; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, h->size, max_chain_len); } libsepol/src/hierarchy.c0100644 0000000 0000000 00000041755 13756670065 014362 0ustar000000000 0000000 /* Authors: Joshua Brindle * Jason Tang * * Updates: KaiGai Kohei * adds checks based on newer boundary facility. * * A set of utility functions that aid policy decision when dealing * with hierarchal namespaces. * * Copyright (C) 2005 Tresys Technology, LLC * * Copyright (c) 2008 NEC Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "debug.h" #define BOUNDS_AVTAB_SIZE 1024 static int bounds_insert_helper(sepol_handle_t *handle, avtab_t *avtab, avtab_key_t *avtab_key, avtab_datum_t *datum) { int rc = avtab_insert(avtab, avtab_key, datum); if (rc) { if (rc == SEPOL_ENOMEM) ERR(handle, "Insufficient memory"); else ERR(handle, "Unexpected error (%d)", rc); } return rc; } static int bounds_insert_rule(sepol_handle_t *handle, avtab_t *avtab, avtab_t *global, avtab_t *other, avtab_key_t *avtab_key, avtab_datum_t *datum) { int rc = 0; avtab_datum_t *dup = avtab_search(avtab, avtab_key); if (!dup) { rc = bounds_insert_helper(handle, avtab, avtab_key, datum); if (rc) goto exit; } else { dup->data |= datum->data; } if (other) { /* Search the other conditional avtab for the key and * add any common permissions to the global avtab */ uint32_t data = 0; dup = avtab_search(other, avtab_key); if (dup) { data = dup->data & datum->data; if (data) { dup = avtab_search(global, avtab_key); if (!dup) { avtab_datum_t d; d.data = data; rc = bounds_insert_helper(handle, global, avtab_key, &d); if (rc) goto exit; } else { dup->data |= data; } } } } exit: return rc; } static int bounds_expand_rule(sepol_handle_t *handle, policydb_t *p, avtab_t *avtab, avtab_t *global, avtab_t *other, uint32_t parent, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data) { int rc = 0; avtab_key_t avtab_key; avtab_datum_t datum; ebitmap_node_t *tnode; unsigned int i; avtab_key.specified = AVTAB_ALLOWED; avtab_key.target_class = class; datum.data = data; if (ebitmap_get_bit(&p->attr_type_map[src - 1], parent - 1)) { avtab_key.source_type = parent; ebitmap_for_each_bit(&p->attr_type_map[tgt - 1], tnode, i) { if (!ebitmap_node_get_bit(tnode, i)) continue; avtab_key.target_type = i + 1; rc = bounds_insert_rule(handle, avtab, global, other, &avtab_key, &datum); if (rc) goto exit; } } exit: return rc; } static int bounds_expand_cond_rules(sepol_handle_t *handle, policydb_t *p, cond_av_list_t *cur, avtab_t *avtab, avtab_t *global, avtab_t *other, uint32_t parent) { int rc = 0; for (; cur; cur = cur->next) { avtab_ptr_t n = cur->node; rc = bounds_expand_rule(handle, p, avtab, global, other, parent, n->key.source_type, n->key.target_type, n->key.target_class, n->datum.data); if (rc) goto exit; } exit: return rc; } struct bounds_expand_args { sepol_handle_t *handle; policydb_t *p; avtab_t *avtab; uint32_t parent; }; static int bounds_expand_rule_callback(avtab_key_t *k, avtab_datum_t *d, void *args) { struct bounds_expand_args *a = (struct bounds_expand_args *)args; if (!(k->specified & AVTAB_ALLOWED)) return 0; return bounds_expand_rule(a->handle, a->p, a->avtab, NULL, NULL, a->parent, k->source_type, k->target_type, k->target_class, d->data); } struct bounds_cond_info { avtab_t true_avtab; avtab_t false_avtab; cond_list_t *cond_list; struct bounds_cond_info *next; }; static void bounds_destroy_cond_info(struct bounds_cond_info *cur) { struct bounds_cond_info *next; for (; cur; cur = next) { next = cur->next; avtab_destroy(&cur->true_avtab); avtab_destroy(&cur->false_avtab); cur->next = NULL; free(cur); } } static int bounds_expand_parent_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, struct bounds_cond_info **cond_info, uint32_t parent) { int rc = 0; struct bounds_expand_args args; cond_list_t *cur; avtab_init(global_avtab); rc = avtab_alloc(global_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; args.handle = handle; args.p = p; args.avtab = global_avtab; args.parent = parent; rc = avtab_map(&p->te_avtab, bounds_expand_rule_callback, &args); if (rc) goto exit; *cond_info = NULL; for (cur = p->cond_list; cur; cur = cur->next) { struct bounds_cond_info *ci; ci = malloc(sizeof(struct bounds_cond_info)); if (!ci) goto oom; avtab_init(&ci->true_avtab); avtab_init(&ci->false_avtab); ci->cond_list = cur; ci->next = *cond_info; *cond_info = ci; if (cur->true_list) { rc = avtab_alloc(&ci->true_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; rc = bounds_expand_cond_rules(handle, p, cur->true_list, &ci->true_avtab, NULL, NULL, parent); if (rc) goto exit; } if (cur->false_list) { rc = avtab_alloc(&ci->false_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; rc = bounds_expand_cond_rules(handle, p, cur->false_list, &ci->false_avtab, global_avtab, &ci->true_avtab, parent); if (rc) goto exit; } } return 0; oom: ERR(handle, "Insufficient memory"); exit: ERR(handle,"Failed to expand parent rules\n"); avtab_destroy(global_avtab); bounds_destroy_cond_info(*cond_info); *cond_info = NULL; return rc; } static int bounds_not_covered(avtab_t *global_avtab, avtab_t *cur_avtab, avtab_key_t *avtab_key, uint32_t data) { avtab_datum_t *datum = avtab_search(cur_avtab, avtab_key); if (datum) data &= ~datum->data; if (global_avtab && data) { datum = avtab_search(global_avtab, avtab_key); if (datum) data &= ~datum->data; } return data; } static int bounds_add_bad(sepol_handle_t *handle, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data, avtab_ptr_t *bad) { struct avtab_node *new = malloc(sizeof(struct avtab_node)); if (new == NULL) { ERR(handle, "Insufficient memory"); return SEPOL_ENOMEM; } memset(new, 0, sizeof(struct avtab_node)); new->key.source_type = src; new->key.target_type = tgt; new->key.target_class = class; new->datum.data = data; new->next = *bad; *bad = new; return 0; } static int bounds_check_rule(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, avtab_t *cur_avtab, uint32_t child, uint32_t parent, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data, avtab_ptr_t *bad, int *numbad) { int rc = 0; avtab_key_t avtab_key; type_datum_t *td; ebitmap_node_t *tnode; unsigned int i; uint32_t d; avtab_key.specified = AVTAB_ALLOWED; avtab_key.target_class = class; if (ebitmap_get_bit(&p->attr_type_map[src - 1], child - 1)) { avtab_key.source_type = parent; ebitmap_for_each_bit(&p->attr_type_map[tgt - 1], tnode, i) { if (!ebitmap_node_get_bit(tnode, i)) continue; td = p->type_val_to_struct[i]; if (td && td->bounds) { avtab_key.target_type = td->bounds; d = bounds_not_covered(global_avtab, cur_avtab, &avtab_key, data); } else { avtab_key.target_type = i + 1; d = bounds_not_covered(global_avtab, cur_avtab, &avtab_key, data); } if (d) { (*numbad)++; rc = bounds_add_bad(handle, child, i+1, class, d, bad); if (rc) goto exit; } } } exit: return rc; } static int bounds_check_cond_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, avtab_t *cond_avtab, cond_av_list_t *rules, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc = 0; cond_av_list_t *cur; for (cur = rules; cur; cur = cur->next) { avtab_ptr_t ap = cur->node; avtab_key_t *key = &ap->key; avtab_datum_t *datum = &ap->datum; if (!(key->specified & AVTAB_ALLOWED)) continue; rc = bounds_check_rule(handle, p, global_avtab, cond_avtab, child, parent, key->source_type, key->target_type, key->target_class, datum->data, bad, numbad); if (rc) goto exit; } exit: return rc; } struct bounds_check_args { sepol_handle_t *handle; policydb_t *p; avtab_t *cur_avtab; uint32_t child; uint32_t parent; avtab_ptr_t bad; int numbad; }; static int bounds_check_rule_callback(avtab_key_t *k, avtab_datum_t *d, void *args) { struct bounds_check_args *a = (struct bounds_check_args *)args; if (!(k->specified & AVTAB_ALLOWED)) return 0; return bounds_check_rule(a->handle, a->p, NULL, a->cur_avtab, a->child, a->parent, k->source_type, k->target_type, k->target_class, d->data, &a->bad, &a->numbad); } static int bounds_check_child_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, struct bounds_cond_info *cond_info, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc; struct bounds_check_args args; struct bounds_cond_info *cur; args.handle = handle; args.p = p; args.cur_avtab = global_avtab; args.child = child; args.parent = parent; args.bad = NULL; args.numbad = 0; rc = avtab_map(&p->te_avtab, bounds_check_rule_callback, &args); if (rc) goto exit; for (cur = cond_info; cur; cur = cur->next) { cond_list_t *node = cur->cond_list; rc = bounds_check_cond_rules(handle, p, global_avtab, &cur->true_avtab, node->true_list, child, parent, &args.bad, &args.numbad); if (rc) goto exit; rc = bounds_check_cond_rules(handle, p, global_avtab, &cur->false_avtab, node->false_list, child, parent, &args.bad, &args.numbad); if (rc) goto exit; } *numbad += args.numbad; *bad = args.bad; exit: return rc; } int bounds_check_type(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc = 0; avtab_t global_avtab; struct bounds_cond_info *cond_info = NULL; rc = bounds_expand_parent_rules(handle, p, &global_avtab, &cond_info, parent); if (rc) goto exit; rc = bounds_check_child_rules(handle, p, &global_avtab, cond_info, child, parent, bad, numbad); bounds_destroy_cond_info(cond_info); avtab_destroy(&global_avtab); exit: return rc; } struct bounds_args { sepol_handle_t *handle; policydb_t *p; int numbad; }; static void bounds_report(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t cur) { ERR(handle, "Child type %s exceeds bounds of parent %s in the following rules:", p->p_type_val_to_name[child - 1], p->p_type_val_to_name[parent - 1]); for (; cur; cur = cur->next) { ERR(handle, " %s %s : %s { %s }", p->p_type_val_to_name[cur->key.source_type - 1], p->p_type_val_to_name[cur->key.target_type - 1], p->p_class_val_to_name[cur->key.target_class - 1], sepol_av_to_string(p, cur->key.target_class, cur->datum.data)); } } void bounds_destroy_bad(avtab_ptr_t cur) { avtab_ptr_t next; for (; cur; cur = next) { next = cur->next; cur->next = NULL; free(cur); } } static int bounds_check_type_callback(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args) { int rc = 0; struct bounds_args *a = (struct bounds_args *)args; type_datum_t *t = (type_datum_t *)d; avtab_ptr_t bad = NULL; if (t->bounds) { rc = bounds_check_type(a->handle, a->p, t->s.value, t->bounds, &bad, &a->numbad); if (bad) { bounds_report(a->handle, a->p, t->s.value, t->bounds, bad); bounds_destroy_bad(bad); } } return rc; } int bounds_check_types(sepol_handle_t *handle, policydb_t *p) { int rc; struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; rc = hashtab_map(p->p_types.table, bounds_check_type_callback, &args); if (rc) goto exit; if (args.numbad > 0) { ERR(handle, "%d errors found during type bounds check", args.numbad); rc = SEPOL_ERR; } exit: return rc; } /* The role bounds is defined as: a child role cannot have a type that * its parent doesn't have. */ static int bounds_check_role_callback(hashtab_key_t k, hashtab_datum_t d, void *args) { struct bounds_args *a = (struct bounds_args *)args; role_datum_t *r = (role_datum_t *) d; role_datum_t *rp = NULL; if (!r->bounds) return 0; rp = a->p->role_val_to_struct[r->bounds - 1]; if (rp && !ebitmap_contains(&rp->types.types, &r->types.types)) { ERR(a->handle, "Role bounds violation, %s exceeds %s", (char *)k, a->p->p_role_val_to_name[rp->s.value - 1]); a->numbad++; } return 0; } int bounds_check_roles(sepol_handle_t *handle, policydb_t *p) { struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; hashtab_map(p->p_roles.table, bounds_check_role_callback, &args); if (args.numbad > 0) { ERR(handle, "%d errors found during role bounds check", args.numbad); return SEPOL_ERR; } return 0; } /* The user bounds is defined as: a child user cannot have a role that * its parent doesn't have. */ static int bounds_check_user_callback(hashtab_key_t k, hashtab_datum_t d, void *args) { struct bounds_args *a = (struct bounds_args *)args; user_datum_t *u = (user_datum_t *) d; user_datum_t *up = NULL; if (!u->bounds) return 0; up = a->p->user_val_to_struct[u->bounds - 1]; if (up && !ebitmap_contains(&up->roles.roles, &u->roles.roles)) { ERR(a->handle, "User bounds violation, %s exceeds %s", (char *) k, a->p->p_user_val_to_name[up->s.value - 1]); a->numbad++; } return 0; } int bounds_check_users(sepol_handle_t *handle, policydb_t *p) { struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; hashtab_map(p->p_users.table, bounds_check_user_callback, &args); if (args.numbad > 0) { ERR(handle, "%d errors found during user bounds check", args.numbad); return SEPOL_ERR; } return 0; } #define add_hierarchy_callback_template(prefix) \ int hierarchy_add_##prefix##_callback(hashtab_key_t k __attribute__ ((unused)), \ hashtab_datum_t d, void *args) \ { \ struct bounds_args *a = (struct bounds_args *)args; \ sepol_handle_t *handle = a->handle; \ policydb_t *p = a->p; \ prefix##_datum_t *datum = (prefix##_datum_t *)d; \ prefix##_datum_t *parent; \ char *parent_name, *datum_name, *tmp; \ \ if (!datum->bounds) { \ datum_name = p->p_##prefix##_val_to_name[datum->s.value - 1]; \ \ tmp = strrchr(datum_name, '.'); \ /* no '.' means it has no parent */ \ if (!tmp) return 0; \ \ parent_name = strdup(datum_name); \ if (!parent_name) { \ ERR(handle, "Insufficient memory"); \ return SEPOL_ENOMEM; \ } \ parent_name[tmp - datum_name] = '\0'; \ \ parent = hashtab_search(p->p_##prefix##s.table, parent_name); \ if (!parent) { \ /* Orphan type/role/user */ \ ERR(handle, "%s doesn't exist, %s is an orphan",\ parent_name, \ p->p_##prefix##_val_to_name[datum->s.value - 1]); \ free(parent_name); \ a->numbad++; \ return 0; \ } \ datum->bounds = parent->s.value; \ free(parent_name); \ } \ \ return 0; \ } \ static add_hierarchy_callback_template(type) static add_hierarchy_callback_template(role) static add_hierarchy_callback_template(user) int hierarchy_add_bounds(sepol_handle_t *handle, policydb_t *p) { int rc = 0; struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; rc = hashtab_map(p->p_users.table, hierarchy_add_user_callback, &args); if (rc) goto exit; rc = hashtab_map(p->p_roles.table, hierarchy_add_role_callback, &args); if (rc) goto exit; rc = hashtab_map(p->p_types.table, hierarchy_add_type_callback, &args); if (rc) goto exit; if (args.numbad > 0) { ERR(handle, "%d errors found while adding hierarchies", args.numbad); rc = SEPOL_ERR; } exit: return rc; } int hierarchy_check_constraints(sepol_handle_t * handle, policydb_t * p) { int rc = 0; int violation = 0; rc = hierarchy_add_bounds(handle, p); if (rc) goto exit; rc = bounds_check_users(handle, p); if (rc) violation = 1; rc = bounds_check_roles(handle, p); if (rc) violation = 1; rc = bounds_check_types(handle, p); if (rc) { if (rc == SEPOL_ERR) violation = 1; else goto exit; } if (violation) rc = SEPOL_ERR; exit: return rc; } libsepol/src/ibendport_internal.h0100644 0000000 0000000 00000001064 13756670065 016260 0ustar000000000 0000000 #ifndef _SEPOL_IBENDPORT_INTERNAL_H_ #define _SEPOL_IBENDPORT_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_ibendport_create) hidden_proto(sepol_ibendport_free) hidden_proto(sepol_ibendport_get_con) hidden_proto(sepol_ibendport_get_port) hidden_proto(sepol_ibendport_key_create) hidden_proto(sepol_ibendport_key_unpack) hidden_proto(sepol_ibendport_set_con) hidden_proto(sepol_ibendport_set_port) hidden_proto(sepol_ibendport_get_ibdev_name) hidden_proto(sepol_ibendport_set_ibdev_name) #endif libsepol/src/ibendport_record.c0100644 0000000 0000000 00000014541 13756670065 015721 0ustar000000000 0000000 #include #include #include #include #include #include "sepol/policydb/policydb.h" #include "ibendport_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_ibendport { /* Device Name */ char *ibdev_name; /* Port number */ int port; /* Context */ sepol_context_t *con; }; struct sepol_ibendport_key { /* Device Name */ char *ibdev_name; /* Port number */ int port; }; /* Allocates a sufficiently large string (ibdev_name) */ int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, char **ibdev_name) { *ibdev_name = calloc(1, IB_DEVICE_NAME_MAX); if (!*ibdev_name) goto omem; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); ERR(handle, "could not allocate string buffer for ibdev_name"); return STATUS_ERR; } /* Key */ int sepol_ibendport_key_create(sepol_handle_t *handle, const char *ibdev_name, int port, sepol_ibendport_key_t **key_ptr) { sepol_ibendport_key_t *tmp_key = (sepol_ibendport_key_t *)malloc(sizeof(sepol_ibendport_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create ibendport key"); goto omem; } if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0) goto err; strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX); tmp_key->port = port; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_ibendport_key_free(tmp_key); ERR(handle, "could not create ibendport key for IB device %s, port %u", ibdev_name, port); return STATUS_ERR; } hidden_def(sepol_ibendport_key_create) void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, const char **ibdev_name, int *port) { *ibdev_name = key->ibdev_name; *port = key->port; } hidden_def(sepol_ibendport_key_unpack) int sepol_ibendport_key_extract(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_key_t **key_ptr) { if (sepol_ibendport_key_create (handle, ibendport->ibdev_name, ibendport->port, key_ptr) < 0) { ERR(handle, "could not extract key from ibendport device %s port %d", ibendport->ibdev_name, ibendport->port); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_ibendport_key_free(sepol_ibendport_key_t *key) { if (!key) return; free(key->ibdev_name); free(key); } int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key) { int rc; rc = strcmp(ibendport->ibdev_name, key->ibdev_name); if ((ibendport->port == key->port) && !rc) return 0; if (ibendport->port < key->port) return -1; else if (key->port < ibendport->port) return 1; else return rc; } int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2) { int rc; rc = strcmp(ibendport->ibdev_name, ibendport2->ibdev_name); if ((ibendport->port == ibendport2->port) && !rc) return 0; if (ibendport->port < ibendport2->port) return -1; else if (ibendport2->port < ibendport->port) return 1; else return rc; } int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport) { return ibendport->port; } hidden_def(sepol_ibendport_get_port) void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port) { ibendport->port = port; } hidden_def(sepol_ibendport_set_port) int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, char **ibdev_name) { char *tmp_ibdev_name = NULL; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0) goto err; strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX); *ibdev_name = tmp_ibdev_name; return STATUS_SUCCESS; err: free(tmp_ibdev_name); ERR(handle, "could not get ibendport ibdev_name"); return STATUS_ERR; } hidden_def(sepol_ibendport_get_ibdev_name) int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, sepol_ibendport_t *ibendport, const char *ibdev_name) { char *tmp = NULL; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0) goto err; strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX); free(ibendport->ibdev_name); ibendport->ibdev_name = tmp; return STATUS_SUCCESS; err: free(tmp); ERR(handle, "could not set ibendport subnet prefix to %s", ibdev_name); return STATUS_ERR; } hidden_def(sepol_ibendport_set_ibdev_name) /* Create */ int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport) { sepol_ibendport_t *tmp_ibendport = (sepol_ibendport_t *)malloc(sizeof(sepol_ibendport_t)); if (!tmp_ibendport) { ERR(handle, "out of memory, could not create ibendport record"); return STATUS_ERR; } tmp_ibendport->ibdev_name = NULL; tmp_ibendport->port = 0; tmp_ibendport->con = NULL; *ibendport = tmp_ibendport; return STATUS_SUCCESS; } hidden_def(sepol_ibendport_create) /* Deep copy clone */ int sepol_ibendport_clone(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_t **ibendport_ptr) { sepol_ibendport_t *new_ibendport = NULL; if (sepol_ibendport_create(handle, &new_ibendport) < 0) goto err; if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0) goto omem; strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX); new_ibendport->port = ibendport->port; if (ibendport->con && (sepol_context_clone(handle, ibendport->con, &new_ibendport->con) < 0)) goto err; *ibendport_ptr = new_ibendport; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone ibendport record"); sepol_ibendport_free(new_ibendport); return STATUS_ERR; } /* Destroy */ void sepol_ibendport_free(sepol_ibendport_t *ibendport) { if (!ibendport) return; free(ibendport->ibdev_name); sepol_context_free(ibendport->con); free(ibendport); } hidden_def(sepol_ibendport_free) /* Context */ sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport) { return ibendport->con; } hidden_def(sepol_ibendport_get_con) int sepol_ibendport_set_con(sepol_handle_t *handle, sepol_ibendport_t *ibendport, sepol_context_t *con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set ibendport context"); return STATUS_ERR; } sepol_context_free(ibendport->con); ibendport->con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_ibendport_set_con) libsepol/src/ibendports.c0100644 0000000 0000000 00000013540 13756670065 014544 0ustar000000000 0000000 #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "ibendport_internal.h" /* Create a low level ibendport structure from * a high level representation */ static int ibendport_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibendport, const sepol_ibendport_t *data) { ocontext_t *tmp_ibendport = NULL; context_struct_t *tmp_con = NULL; char *ibdev_name = NULL; int port = sepol_ibendport_get_port(data); tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t)); if (!tmp_ibendport) goto omem; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibendport->u.ibendport.dev_name) < 0) goto omem; if (sepol_ibendport_get_ibdev_name(handle, data, &ibdev_name) < 0) goto err; strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX); free(ibdev_name); ibdev_name = NULL; tmp_ibendport->u.ibendport.port = port; /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibendport_get_con(data)) < 0) goto err; context_cpy(&tmp_ibendport->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibendport = tmp_ibendport; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibendport) { context_destroy(&tmp_ibendport->context[0]); free(tmp_ibendport); } context_destroy(tmp_con); free(tmp_con); free(ibdev_name); ERR(handle, "could not create ibendport structure"); return STATUS_ERR; } static int ibendport_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibendport, sepol_ibendport_t **record) { int port = ibendport->u.ibendport.port; context_struct_t *con = &ibendport->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibendport_t *tmp_record = NULL; if (sepol_ibendport_create(handle, &tmp_record) < 0) goto err; if (sepol_ibendport_set_ibdev_name(handle, tmp_record, ibendport->u.ibendport.dev_name) < 0) goto err; sepol_ibendport_set_port(tmp_record, port); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibendport to record"); sepol_context_free(tmp_con); sepol_ibendport_free(tmp_record); return STATUS_ERR; } /* Return the number of ibendports */ extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibendport exists */ int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibendport_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } int sepol_ibendport_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibendport_key_t *key, sepol_ibendport_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { if (ibendport_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibendport, IB device: %s port %u", ibdev_name, port); return STATUS_ERR; } /* Load a ibendport into policy */ int sepol_ibendport_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibendport_key_t *key, const sepol_ibendport_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibendport = NULL; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); if (ibendport_from_record(handle, policydb, &ibendport, data) < 0) goto err; /* Attach to context list */ ibendport->next = policydb->ocontexts[OCON_IBENDPORT]; policydb->ocontexts[OCON_IBENDPORT] = ibendport; return STATUS_SUCCESS; err: ERR(handle, "could not load ibendport %s/%d", ibdev_name, port); if (ibendport) { context_destroy(&ibendport->context[0]); free(ibendport); } return STATUS_ERR; } int sepol_ibendport_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibendport_t *ibendport, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibendport_t *ibendport = NULL; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { int status; if (ibendport_to_record(handle, policydb, c, &ibendport) < 0) goto err; /* Invoke handler */ status = fn(ibendport, arg); if (status < 0) goto err; sepol_ibendport_free(ibendport); ibendport = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibendports"); sepol_ibendport_free(ibendport); return STATUS_ERR; } libsepol/src/ibpkey_internal.h0100644 0000000 0000000 00000001232 13756670065 015552 0ustar000000000 0000000 #ifndef _SEPOL_IBPKEY_INTERNAL_H_ #define _SEPOL_IBPKEY_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_ibpkey_create) hidden_proto(sepol_ibpkey_free) hidden_proto(sepol_ibpkey_get_con) hidden_proto(sepol_ibpkey_get_high) hidden_proto(sepol_ibpkey_get_low) hidden_proto(sepol_ibpkey_key_create) hidden_proto(sepol_ibpkey_key_unpack) hidden_proto(sepol_ibpkey_set_con) hidden_proto(sepol_ibpkey_set_range) hidden_proto(sepol_ibpkey_get_subnet_prefix) hidden_proto(sepol_ibpkey_get_subnet_prefix_bytes) hidden_proto(sepol_ibpkey_set_subnet_prefix) hidden_proto(sepol_ibpkey_set_subnet_prefix_bytes) #endif libsepol/src/ibpkey_record.c0100644 0000000 0000000 00000020310 13756670065 015205 0ustar000000000 0000000 #include #include #include #include #include #include #include "ibpkey_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_ibpkey { /* Subnet prefix */ uint64_t subnet_prefix; /* Low - High range. Same for single ibpkeys. */ int low, high; /* Context */ sepol_context_t *con; }; struct sepol_ibpkey_key { /* Subnet prefix */ uint64_t subnet_prefix; /* Low - High range. Same for single ibpkeys. */ int low, high; }; /* Converts a string represtation (subnet_prefix_str) * to a numeric representation (subnet_prefix_bytes) */ static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle, const char *subnet_prefix_str, uint64_t *subnet_prefix) { struct in6_addr in_addr; if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s", subnet_prefix_str, strerror(errno)); return STATUS_ERR; } memcpy(subnet_prefix, in_addr.s6_addr, sizeof(*subnet_prefix)); return STATUS_SUCCESS; } /* Converts a numeric representation (subnet_prefix_bytes) * to a string representation (subnet_prefix_str) */ static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle, uint64_t subnet_prefix, char *subnet_prefix_str) { struct in6_addr addr; memset(&addr, 0, sizeof(struct in6_addr)); memcpy(&addr.s6_addr[0], &subnet_prefix, sizeof(subnet_prefix)); if (inet_ntop(AF_INET6, &addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv6 address to string: %s", strerror(errno)); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large string (subnet_prefix) * for an IPV6 address for the subnet prefix */ static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle, char **subnet_prefix) { char *tmp_subnet_prefix = NULL; tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN); if (!tmp_subnet_prefix) goto omem; *subnet_prefix = tmp_subnet_prefix; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); ERR(handle, "could not allocate string buffer for subnet_prefix"); return STATUS_ERR; } /* Key */ int sepol_ibpkey_key_create(sepol_handle_t *handle, const char *subnet_prefix, int low, int high, sepol_ibpkey_key_t **key_ptr) { sepol_ibpkey_key_t *tmp_key = (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create ibpkey key"); goto omem; } if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0) goto err; tmp_key->low = low; tmp_key->high = high; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_ibpkey_key_free(tmp_key); ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u", subnet_prefix, low, high); return STATUS_ERR; } hidden_def(sepol_ibpkey_key_create) void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, uint64_t *subnet_prefix, int *low, int *high) { *subnet_prefix = key->subnet_prefix; *low = key->low; *high = key->high; } hidden_def(sepol_ibpkey_key_unpack) int sepol_ibpkey_key_extract(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_key_t **key_ptr) { char subnet_prefix_str[INET6_ADDRSTRLEN]; ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str); if (sepol_ibpkey_key_create (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) { ERR(handle, "could not extract key from ibpkey %s %d:%d", subnet_prefix_str, ibpkey->low, ibpkey->high); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key) { if (!key) return; free(key); } int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key) { if (ibpkey->subnet_prefix < key->subnet_prefix) return -1; if (key->subnet_prefix < ibpkey->subnet_prefix) return 1; if (ibpkey->low < key->low) return -1; if (key->low < ibpkey->low) return 1; if (ibpkey->high < key->high) return -1; if (key->high < ibpkey->high) return 1; return 0; } int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2) { if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix) return -1; if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix) return 1; if (ibpkey->low < ibpkey2->low) return -1; if (ibpkey2->low < ibpkey->low) return 1; if (ibpkey->high < ibpkey2->high) return -1; if (ibpkey2->high < ibpkey->high) return 1; return 0; } /* Pkey */ int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey) { return ibpkey->low; } hidden_def(sepol_ibpkey_get_low) int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey) { return ibpkey->high; } hidden_def(sepol_ibpkey_get_high) void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num) { ibpkey->low = pkey_num; ibpkey->high = pkey_num; } void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high) { ibpkey->low = low; ibpkey->high = high; } hidden_def(sepol_ibpkey_set_range) int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, char **subnet_prefix) { char *tmp_subnet_prefix = NULL; if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0) goto err; if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0) goto err; *subnet_prefix = tmp_subnet_prefix; return STATUS_SUCCESS; err: free(tmp_subnet_prefix); ERR(handle, "could not get ibpkey subnet_prefix"); return STATUS_ERR; } hidden_def(sepol_ibpkey_get_subnet_prefix) /* Subnet prefix */ uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey) { return ibpkey->subnet_prefix; } hidden_def(sepol_ibpkey_get_subnet_prefix_bytes) int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, const char *subnet_prefix_str) { uint64_t tmp = 0; if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0) goto err; ibpkey->subnet_prefix = tmp; return STATUS_SUCCESS; err: ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str); return STATUS_ERR; } hidden_def(sepol_ibpkey_set_subnet_prefix) void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, uint64_t subnet_prefix) { ibpkey->subnet_prefix = subnet_prefix; } hidden_def(sepol_ibpkey_set_subnet_prefix_bytes) /* Create */ int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey) { sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t)); if (!tmp_ibpkey) { ERR(handle, "out of memory, could not create ibpkey record"); return STATUS_ERR; } tmp_ibpkey->subnet_prefix = 0; tmp_ibpkey->low = 0; tmp_ibpkey->high = 0; tmp_ibpkey->con = NULL; *ibpkey = tmp_ibpkey; return STATUS_SUCCESS; } hidden_def(sepol_ibpkey_create) /* Deep copy clone */ int sepol_ibpkey_clone(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr) { sepol_ibpkey_t *new_ibpkey = NULL; if (sepol_ibpkey_create(handle, &new_ibpkey) < 0) goto err; new_ibpkey->subnet_prefix = ibpkey->subnet_prefix; new_ibpkey->low = ibpkey->low; new_ibpkey->high = ibpkey->high; if (ibpkey->con && (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0)) goto err; *ibpkey_ptr = new_ibpkey; return STATUS_SUCCESS; err: ERR(handle, "could not clone ibpkey record"); sepol_ibpkey_free(new_ibpkey); return STATUS_ERR; } /* Destroy */ void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey) { if (!ibpkey) return; sepol_context_free(ibpkey->con); free(ibpkey); } hidden_def(sepol_ibpkey_free) /* Context */ sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey) { return ibpkey->con; } hidden_def(sepol_ibpkey_get_con) int sepol_ibpkey_set_con(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, sepol_context_t *con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set ibpkey context"); return STATUS_ERR; } sepol_context_free(ibpkey->con); ibpkey->con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_ibpkey_set_con) libsepol/src/ibpkeys.c0100644 0000000 0000000 00000013760 13756670065 014045 0ustar000000000 0000000 #include #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include #include "ibpkey_internal.h" /* Create a low level ibpkey structure from * a high level representation */ static int ibpkey_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibpkey, const sepol_ibpkey_t *data) { ocontext_t *tmp_ibpkey = NULL; context_struct_t *tmp_con = NULL; char *subnet_prefix_buf = NULL; int low = sepol_ibpkey_get_low(data); int high = sepol_ibpkey_get_high(data); tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); if (!tmp_ibpkey) goto omem; tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); /* Pkey range */ tmp_ibpkey->u.ibpkey.low_pkey = low; tmp_ibpkey->u.ibpkey.high_pkey = high; if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { ERR(handle, "low ibpkey %d exceeds high ibpkey %d", tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); goto err; } /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibpkey_get_con(data)) < 0) goto err; context_cpy(&tmp_ibpkey->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibpkey = tmp_ibpkey; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibpkey) { context_destroy(&tmp_ibpkey->context[0]); free(tmp_ibpkey); } context_destroy(tmp_con); free(tmp_con); free(subnet_prefix_buf); ERR(handle, "could not create ibpkey structure"); return STATUS_ERR; } static int ibpkey_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibpkey, sepol_ibpkey_t **record) { context_struct_t *con = &ibpkey->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibpkey_t *tmp_record = NULL; if (sepol_ibpkey_create(handle, &tmp_record) < 0) goto err; sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, ibpkey->u.ibpkey.subnet_prefix); sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, ibpkey->u.ibpkey.high_pkey); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibpkey to record"); sepol_context_free(tmp_con); sepol_ibpkey_free(tmp_record); return STATUS_ERR; } /* Return the number of ibpkeys */ extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibpkey exists */ int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; uint16_t low2 = c->u.ibpkey.low_pkey; uint16_t high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } /* Query a ibpkey */ int sepol_ibpkey_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; int low2 = c->u.ibpkey.low_pkey; int high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { if (ibpkey_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); return STATUS_ERR; } /* Load a ibpkey into policy */ int sepol_ibpkey_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibpkey = NULL; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) goto err; /* Attach to context list */ ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; policydb->ocontexts[OCON_IBPKEY] = ibpkey; return STATUS_SUCCESS; err: ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); if (ibpkey) { context_destroy(&ibpkey->context[0]); free(ibpkey); } return STATUS_ERR; } int sepol_ibpkey_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibpkey_t *ibpkey, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibpkey_t *ibpkey = NULL; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { int status; if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) goto err; /* Invoke handler */ status = fn(ibpkey, arg); if (status < 0) goto err; sepol_ibpkey_free(ibpkey); ibpkey = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibpkeys"); sepol_ibpkey_free(ibpkey); return STATUS_ERR; } libsepol/src/iface_internal.h0100644 0000000 0000000 00000001040 13756670065 015333 0ustar000000000 0000000 #ifndef _SEPOL_IFACE_INTERNAL_H_ #define _SEPOL_IFACE_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_iface_create) hidden_proto(sepol_iface_free) hidden_proto(sepol_iface_get_ifcon) hidden_proto(sepol_iface_get_msgcon) hidden_proto(sepol_iface_get_name) hidden_proto(sepol_iface_key_create) hidden_proto(sepol_iface_key_unpack) hidden_proto(sepol_iface_set_ifcon) hidden_proto(sepol_iface_set_msgcon) hidden_proto(sepol_iface_set_name) #endif libsepol/src/iface_record.c0100644 0000000 0000000 00000011260 13756670065 014775 0ustar000000000 0000000 #include #include #include "iface_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_iface { /* Interface name */ char *name; /* Interface context */ sepol_context_t *netif_con; /* Message context */ sepol_context_t *netmsg_con; }; struct sepol_iface_key { /* Interface name */ char *name; }; /* Key */ int sepol_iface_key_create(sepol_handle_t * handle, const char *name, sepol_iface_key_t ** key_ptr) { sepol_iface_key_t *tmp_key = (sepol_iface_key_t *) malloc(sizeof(sepol_iface_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create interface key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, could not create interface key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(sepol_iface_key_create) void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name) { *name = key->name; } hidden_def(sepol_iface_key_unpack) int sepol_iface_key_extract(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_key_t ** key_ptr) { if (sepol_iface_key_create(handle, iface->name, key_ptr) < 0) { ERR(handle, "could not extract key from " "interface %s", iface->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_iface_key_free(sepol_iface_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_iface_compare(const sepol_iface_t * iface, const sepol_iface_key_t * key) { return strcmp(iface->name, key->name); } int sepol_iface_compare2(const sepol_iface_t * iface, const sepol_iface_t * iface2) { return strcmp(iface->name, iface2->name); } /* Create */ int sepol_iface_create(sepol_handle_t * handle, sepol_iface_t ** iface) { sepol_iface_t *tmp_iface = (sepol_iface_t *) malloc(sizeof(sepol_iface_t)); if (!tmp_iface) { ERR(handle, "out of memory, could not create " "interface record"); return STATUS_ERR; } tmp_iface->name = NULL; tmp_iface->netif_con = NULL; tmp_iface->netmsg_con = NULL; *iface = tmp_iface; return STATUS_SUCCESS; } hidden_def(sepol_iface_create) /* Name */ const char *sepol_iface_get_name(const sepol_iface_t * iface) { return iface->name; } hidden_def(sepol_iface_get_name) int sepol_iface_set_name(sepol_handle_t * handle, sepol_iface_t * iface, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, " "could not set interface name"); return STATUS_ERR; } free(iface->name); iface->name = tmp_name; return STATUS_SUCCESS; } hidden_def(sepol_iface_set_name) /* Interface Context */ sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface) { return iface->netif_con; } hidden_def(sepol_iface_get_ifcon) int sepol_iface_set_ifcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set interface context"); return STATUS_ERR; } sepol_context_free(iface->netif_con); iface->netif_con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_iface_set_ifcon) /* Message Context */ sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface) { return iface->netmsg_con; } hidden_def(sepol_iface_get_msgcon) int sepol_iface_set_msgcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set message context"); return STATUS_ERR; } sepol_context_free(iface->netmsg_con); iface->netmsg_con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_iface_set_msgcon) /* Deep copy clone */ int sepol_iface_clone(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_t ** iface_ptr) { sepol_iface_t *new_iface = NULL; if (sepol_iface_create(handle, &new_iface) < 0) goto err; if (sepol_iface_set_name(handle, new_iface, iface->name) < 0) goto err; if (iface->netif_con && (sepol_context_clone (handle, iface->netif_con, &new_iface->netif_con) < 0)) goto err; if (iface->netmsg_con && (sepol_context_clone (handle, iface->netmsg_con, &new_iface->netmsg_con) < 0)) goto err; *iface_ptr = new_iface; return STATUS_SUCCESS; err: ERR(handle, "could not clone interface record"); sepol_iface_free(new_iface); return STATUS_ERR; } /* Destroy */ void sepol_iface_free(sepol_iface_t * iface) { if (!iface) return; free(iface->name); sepol_context_free(iface->netif_con); sepol_context_free(iface->netmsg_con); free(iface); } hidden_def(sepol_iface_free) libsepol/src/interfaces.c0100644 0000000 0000000 00000013672 13756670065 014524 0ustar000000000 0000000 #include #include "debug.h" #include "context.h" #include "handle.h" #include #include #include "iface_internal.h" /* Create a low level structure from record */ static int iface_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** iface, const sepol_iface_t * record) { ocontext_t *tmp_iface = NULL; context_struct_t *tmp_con = NULL; tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_iface) goto omem; /* Name */ tmp_iface->u.name = strdup(sepol_iface_get_name(record)); if (!tmp_iface->u.name) goto omem; /* Interface Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_iface_get_ifcon(record)) < 0) goto err; context_cpy(&tmp_iface->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; /* Message Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_iface_get_msgcon(record)) < 0) goto err; context_cpy(&tmp_iface->context[1], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *iface = tmp_iface; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_iface != NULL) { free(tmp_iface->u.name); context_destroy(&tmp_iface->context[0]); context_destroy(&tmp_iface->context[1]); free(tmp_iface); } context_destroy(tmp_con); free(tmp_con); ERR(handle, "error creating interface structure"); return STATUS_ERR; } static int iface_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * iface, sepol_iface_t ** record) { char *name = iface->u.name; context_struct_t *ifcon = &iface->context[0]; context_struct_t *msgcon = &iface->context[1]; sepol_context_t *tmp_con = NULL; sepol_iface_t *tmp_record = NULL; if (sepol_iface_create(handle, &tmp_record) < 0) goto err; if (sepol_iface_set_name(handle, tmp_record, name) < 0) goto err; if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0) goto err; if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); tmp_con = NULL; if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0) goto err; if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); tmp_con = NULL; *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert interface %s to record", name); sepol_context_free(tmp_con); sepol_iface_free(tmp_record); return STATUS_ERR; } /* Check if an interface exists */ int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, const sepol_iface_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; const char *name; sepol_iface_key_unpack(key, &name); head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } /* Query an interface */ int sepol_iface_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_iface_key_t * key, sepol_iface_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; const char *name; sepol_iface_key_unpack(key, &name); head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { if (iface_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query interface %s", name); return STATUS_ERR; } /* Load an interface into policy */ int sepol_iface_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_iface_key_t * key, const sepol_iface_t * data) { policydb_t *policydb = &p->p; ocontext_t *head, *prev, *c, *iface = NULL; const char *name; sepol_iface_key_unpack(key, &name); if (iface_from_record(handle, policydb, &iface, data) < 0) goto err; prev = NULL; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { /* Replace */ iface->next = c->next; if (prev == NULL) policydb->ocontexts[OCON_NETIF] = iface; else prev->next = iface; free(c->u.name); context_destroy(&c->context[0]); context_destroy(&c->context[1]); free(c); return STATUS_SUCCESS; } prev = c; } /* Attach to context list */ iface->next = policydb->ocontexts[OCON_NETIF]; policydb->ocontexts[OCON_NETIF] = iface; return STATUS_SUCCESS; err: ERR(handle, "error while loading interface %s", name); if (iface != NULL) { free(iface->u.name); context_destroy(&iface->context[0]); context_destroy(&iface->context[1]); free(iface); } return STATUS_ERR; } /* Return the number of interfaces */ extern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } int sepol_iface_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_iface_t * iface, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_iface_t *iface = NULL; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { int status; if (iface_to_record(handle, policydb, c, &iface) < 0) goto err; /* Invoke handler */ status = fn(iface, arg); if (status < 0) goto err; sepol_iface_free(iface); iface = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over interfaces"); sepol_iface_free(iface); return STATUS_ERR; } libsepol/src/kernel_to_cil.c0100644 0000000 0000000 00000205265 13756670065 015213 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include "kernel_to_common.h" static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) { struct cond_expr *curr; struct strs *stack; char *new_val; char *str = NULL; int rc; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { char *val1 = pdb->p_bool_val_to_name[curr->bool - 1]; new_val = create_str("%s", 1, val1); } else { const char *op; uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch(curr->expr_type) { case COND_NOT: op = "not"; num_params = 1; break; case COND_OR: op = "or"; num_params = 2; break; case COND_AND: op = "and"; num_params = 2; break; case COND_XOR: op = "xor"; num_params = 2; break; case COND_EQ: op = "eq"; num_params = 2; break; case COND_NEQ: op = "neq"; num_params = 2; break; default: sepol_log_err("Unknown conditional operator: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { sepol_log_err("Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { sepol_log_err("Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", 3, op, val1, val2); free(val2); } else { new_val = create_str("(%s %s)", 2, op, val1); } free(val1); } if (!new_val) { sepol_log_err("Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { sepol_log_err("Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { sepol_log_err("Invalid conditional expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); return NULL; } static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls) { struct constraint_expr *curr; struct strs *stack = NULL; char *new_val = NULL; const char *op; char *str = NULL; int rc; *use_mls = 0; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr; curr = curr->next) { if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) { const char *attr1 = NULL; const char *attr2 = NULL; switch (curr->op) { case CEXPR_EQ: op = "eq"; break; case CEXPR_NEQ: op = "neq"; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: sepol_log_err("Unknown constraint operator: %i", curr->op); goto exit; } switch (curr->attr) { case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break; case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break; case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break; case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break; case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break; case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break; case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break; case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: sepol_log_err("Unknown constraint attribute: %i", curr->attr); goto exit; } if (curr->attr >= CEXPR_XTARGET) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { new_val = create_str("(%s %s %s)", 3, op, attr1, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { struct type_set *ts = curr->type_names; names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1); } else if (curr->attr & CEXPR_USER) { names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1); } else if (curr->attr & CEXPR_ROLE) { names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { goto exit; } new_val = create_str("(%s %s %s)", 3, op, attr1, names); free(names); } } else { uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch (curr->expr_type) { case CEXPR_NOT: op = "not"; num_params = 1; break; case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: sepol_log_err("Unknown constraint expression type: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { sepol_log_err("Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { sepol_log_err("Invalid constraint expression"); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", 3, op, val1, val2); free(val2); } else { new_val = create_str("(%s %s)", 2, op, val1); } free(val1); } if (!new_val) { goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { sepol_log_err("Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { sepol_log_err("Invalid constraint expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); return NULL; } static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, class_datum_t *class, struct constraint_node *constraint_rules, struct strs *mls_list, struct strs *non_mls_list) { int rc = 0; struct constraint_node *curr; char *expr = NULL; int is_mls; char *perms; const char *format_str; struct strs *strs; for (curr = constraint_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); if (is_mls) { format_str = "(mlsconstrain (%s (%s)) %s)"; strs = mls_list; } else { format_str = "(constrain (%s (%s)) %s)"; strs = non_mls_list; } rc = strs_create_and_add(strs, format_str, 3, classkey, perms+1, expr); free(expr); if (rc != 0) { goto exit; } } return 0; exit: sepol_log_err("Error gathering constraint rules\n"); return rc; } static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, struct constraint_node *validatetrans_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; char *expr = NULL; int is_mls; const char *format_str; struct strs *strs; int rc = 0; for (curr = validatetrans_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } if (is_mls) { format_str = "(mlsvalidatetrans %s %s)"; strs = mls_list; } else { format_str = "(validatetrans %s %s)"; strs = non_mls_list; } rc = strs_create_and_add(strs, format_str, 2, classkey, expr); free(expr); if (rc != 0) { goto exit; } } exit: return rc; } static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->constraints) { name = pdb->p_class_val_to_name[i]; rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->validatetrans) { name = pdb->p_class_val_to_name[i]; rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb) { const char *action; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: action = "deny"; break; case SEPOL_REJECT_UNKNOWN: action = "reject"; break; case SEPOL_ALLOW_UNKNOWN: action = "allow"; break; default: sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } sepol_printf(out, "(handleunknown %s)\n", action); return 0; } static char *class_or_common_perms_to_str(symtab_t *permtab) { struct strs *strs; char *perms = NULL; int rc; rc = strs_init(&strs, permtab->nprim); if (rc != 0) { goto exit; } rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs); if (rc != 0) { goto exit; } if (strs_num_items(strs) > 0) { perms = strs_to_str(strs); } exit: strs_destroy(&strs); return perms; } static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb) { class_datum_t *class; common_datum_t *common; int *used; char *name, *perms; unsigned i; int rc = 0; /* class */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; name = pdb->p_class_val_to_name[i]; perms = class_or_common_perms_to_str(&class->permissions); if (perms) { sepol_printf(out, "(class %s (%s))\n", name, perms); free(perms); } else { sepol_printf(out, "(class %s ())\n", name); } } /* classorder */ sepol_printf(out, "(classorder ("); name = NULL; for (i=0; i < pdb->p_classes.nprim; i++) { if (name) { sepol_printf(out, "%s ", name); } name = pdb->p_class_val_to_name[i]; } if (name) { sepol_printf(out, "%s", name); } sepol_printf(out, "))\n"); /* classcommon */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; name = pdb->p_class_val_to_name[i]; if (class->comkey != NULL) { sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey); } } /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { sepol_log_err("Out of memory"); rc = -1; goto exit; } for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; name = class->comkey; if (name != NULL) { common = hashtab_search(pdb->p_commons.table, name); if (!common) { rc = -1; free(used); goto exit; } /* Only write common rule once */ if (!used[common->s.value-1]) { perms = class_or_common_perms_to_str(&common->permissions); if (!perms) { rc = -1; free(perms); free(used); goto exit; } sepol_printf(out, "(common %s (%s))\n", name, perms); free(perms); used[common->s.value-1] = 1; } } } free(used); exit: if (rc != 0) { sepol_log_err("Error writing class rules to CIL\n"); } return rc; } static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids) { struct ocontext *isid; struct strs *strs; char *sid; char *prev; char unknown[18]; unsigned i; int rc; rc = strs_init(&strs, num_sids+1); if (rc != 0) { goto exit; } for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = strdup(unknown); } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { goto exit; } } for (i=0; itarget_platform == SEPOL_TARGET_SELINUX) { rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ, pdb->ocontexts[0]); } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ, pdb->ocontexts[0]); } else { sepol_log_err("Unknown target platform: %i", pdb->target_platform); rc = -1; } return rc; } static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_user) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft); return 0; } static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_role) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft); return 0; } static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_type) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft); return 0; } static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_range) { case DEFAULT_SOURCE_LOW: dft = "source low"; break; case DEFAULT_SOURCE_HIGH: dft = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dft = "source low-high"; break; case DEFAULT_TARGET_LOW: dft = "target low"; break; case DEFAULT_TARGET_HIGH: dft = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dft = "target low-high"; break; default: sepol_log_err("Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft); return 0; } static int write_default_rules_to_cil(FILE *out, struct policydb *pdb) { class_datum_t *class; unsigned i; int rc = 0; /* default_user */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_user != 0) { rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_role */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_role != 0) { rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_type */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_type != 0) { rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } if (!pdb->mls) { return 0; } /* default_range */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_range) { rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } exit: if (rc != 0) { sepol_log_err("Error writing default rules to CIL\n"); } return rc; } static void write_default_mls_level(FILE *out) { sepol_printf(out, "(sensitivity s0)"); sepol_printf(out, "(sensitivityorder (s0))"); sepol_printf(out, "(level %s (s0))", DEFAULT_LEVEL); } static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args) { level_datum_t *sens = data; struct strs *strs = args; int rc = 0; if (sens->isalias) { rc = strs_add(strs, key); } return rc; } static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb) { level_datum_t *level; char *prev, *name, *actual; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_levels.nprim); if (rc != 0) { goto exit; } /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; sepol_printf(out, "(sensitivity %s)\n", name); } /* sensitivityorder */ sepol_printf(out, "(sensitivityorder ("); prev = NULL; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, "))\n"); rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); num = strs_num_items(strs); /* sensitivity aliases */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } sepol_printf(out, "(sensitivityalias %s)\n", name); } /* sensitivity aliases to actual */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } actual = pdb->p_sens_val_to_name[level->level->sens - 1]; sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing sensitivity rules to CIL\n"); } return rc; } static int map_category_aliases_to_strs(char *key, void *data, void *args) { cat_datum_t *cat = data; struct strs *strs = args; int rc = 0; if (cat->isalias) { rc = strs_add(strs, key); } return rc; } static int write_category_rules_to_cil(FILE *out, struct policydb *pdb) { cat_datum_t *cat; char *prev, *name, *actual; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_levels.nprim); if (rc != 0) { goto exit; } /* categories */ for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; if (!name) continue; cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } if (cat->isalias) continue; sepol_printf(out, "(category %s)\n", name); } /* categoryorder */ sepol_printf(out, "(categoryorder ("); prev = NULL; for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; if (!name) continue; cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } if (cat->isalias) continue; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, "))\n"); rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); num = strs_num_items(strs); /* category aliases */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } sepol_printf(out, "(categoryalias %s)\n", name); } /* category aliases to actual */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } actual = pdb->p_cat_val_to_name[cat->s.value - 1]; sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing category rules to CIL\n"); } return rc; } static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; size_t len = 0; range = 0; ebitmap_for_each_bit(cats, node, i) { if (!ebitmap_get_bit(cats, i)) continue; if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; len += strlen(val_to_name[start]); if (range > 2) { len += strlen(val_to_name[i-1]) + strlen("(range ) "); } else if (range == 2) { len += strlen(val_to_name[i-1]) + 2; } else if (range == 1) { len += 1; } range = 0; } if (len > 0) { len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */ } return len; } static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; char *catsbuf, *p; const char *fmt; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); catsbuf = malloc(remaining); if (!catsbuf) { goto exit; } p = catsbuf; *p++ = '('; remaining--;; range = 0; ebitmap_for_each_bit(cats, node, i) { if (!ebitmap_get_bit(cats, i)) continue; if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; if (range > 1) { fmt = (range == 2) ? "%s %s " : "(range %s %s) "; len = snprintf(p, remaining, fmt, val_to_name[start], val_to_name[i]); } else { len = snprintf(p, remaining, "%s ", val_to_name[start]); } if (len < 0 || len >= remaining) { goto exit; } p += len; remaining -= len; range = 0; } *(p-1) = ')'; /* Remove trailing ' ' */ *p = '\0'; return catsbuf; exit: free(catsbuf); return NULL; } static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb) { level_datum_t *level; char *name, *cats; unsigned i; int rc = 0; /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (ebitmap_cardinality(&level->level->cat) > 0) { cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name); sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats); free(cats); } } exit: if (rc != 0) { sepol_log_err("Error writing sensitivitycategory rules to CIL\n"); } return rc; } static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb) { int rc = 0; if (!pdb->mls) { sepol_printf(out, "(mls false)\n"); /* CIL requires MLS, even if the kernel binary won't have it */ write_default_mls_level(out); return 0; } sepol_printf(out, "(mls true)\n"); rc = write_sensitivity_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_category_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_sensitivitycategory_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } exit: if (rc != 0) { sepol_log_err("Error writing mls rules to CIL\n"); } return rc; } static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; struct ebitmap_node *node; const char *name; uint32_t i; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } ebitmap_for_each_bit(&pdb->policycaps, node, i) { if (!ebitmap_get_bit(&pdb->policycaps, i)) continue; name = sepol_polcap_getname(i); if (name == NULL) { sepol_log_err("Unknown policy capability id: %i", i); rc = -1; goto exit; } rc = strs_create_and_add(strs, "(policycap %s)", 1, name); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing polcap rules to CIL\n"); } return rc; } static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_ATTRIB) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i = 0; i < num; i++) { name = strs_read_at_index(strs, i); if (!name) { rc = -1; goto exit; } sepol_printf(out, "(typeattribute %s)\n", name); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing typeattribute rules to CIL\n"); } return rc; } static int write_role_attributes_to_cil(FILE *out, struct policydb *pdb) { role_datum_t *role; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ATTRIB) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; istate ? "true" : "false"; return strs_create_and_add(strs, "(boolean %s %s)", 2, key, value); } static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing boolean declarations to CIL\n"); } return rc; } static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *name; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_TYPE && type->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { alias = pdb->type_val_to_struct[i]; if (!alias->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, name); if (!alias) { rc = -1; goto exit; } type = pdb->p_type_val_to_name[alias->s.value - 1]; sepol_printf(out, "(typealiasactual %s %s)\n", name, type); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing type alias rules to CIL\n"); } return rc; } static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *parent; char *child; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_TYPE) { if (type->bounds > 0) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, child); if (!type) { rc = -1; goto exit; } parent = pdb->p_type_val_to_name[type->bounds - 1]; sepol_printf(out, "(typebounds %s %s)\n", parent, child); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing type bounds rules to CIL\n"); } return rc; } static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *attr; struct strs *strs; ebitmap_t *typemap; char *name, *types; unsigned i; int rc; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { attr = pdb->type_val_to_struct[i]; if (attr->flavor != TYPE_ATTRIB) continue; name = pdb->p_type_val_to_name[i]; typemap = &pdb->attr_type_map[i]; if (ebitmap_cardinality(typemap) == 0) continue; types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1); if (!types) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "(typeattributeset %s (%s))", 2, name, types); free(types); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing typeattributeset rules to CIL\n"); } return rc; } static int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; char *name; struct ebitmap_node *node; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } ebitmap_for_each_bit(&pdb->permissive_map, node, i) { if (!ebitmap_get_bit(&pdb->permissive_map, i)) continue; rc = strs_add(strs, pdb->p_type_val_to_name[i-1]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ispecified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) { return NULL; } for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { len = 0; if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value); in_range = 0; } else { len = snprintf(p, remaining, " 0x%hx", value); } } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); in_range = 0; } else { len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); } } if (len < 0 || len >= remaining) { return NULL; } p += len; remaining -= len; } if (remaining < 2) { return NULL; } xpermsbuf[0] = '('; *p++ = ')'; *p = '\0'; return xpermsbuf; } static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum) { uint32_t data = datum->data; type_datum_t *type; const char *flavor, *tgt; char *src, *class, *perms, *new; char *rule = NULL; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: flavor = "allow"; break; case AVTAB_AUDITALLOW: flavor = "auditallow"; break; case AVTAB_AUDITDENY: flavor = "dontaudit"; data = ~data; break; case AVTAB_XPERMS_ALLOWED: flavor = "allowx"; break; case AVTAB_XPERMS_AUDITALLOW: flavor = "auditallowx"; break; case AVTAB_XPERMS_DONTAUDIT: flavor = "dontauditx"; break; case AVTAB_TRANSITION: flavor = "typetransition"; break; case AVTAB_MEMBER: flavor = "typemember"; break; case AVTAB_CHANGE: flavor = "typechange"; break; default: sepol_log_err("Unknown avtab type: %i", key->specified); goto exit; } src = pdb->p_type_val_to_name[key->source_type - 1]; tgt = pdb->p_type_val_to_name[key->target_type - 1]; if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) { type = pdb->type_val_to_struct[key->source_type - 1]; if (type->flavor != TYPE_ATTRIB) { tgt = "self"; } } class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { perms = sepol_av_to_string(pdb, key->target_class, data); if (perms == NULL) { sepol_log_err("Failed to generate permission string"); goto exit; } rule = create_str("(%s %s %s (%s (%s)))", 5, flavor, src, tgt, class, perms+1); } else if (key->specified & AVTAB_XPERMS) { perms = xperms_to_str(datum->xperms); if (perms == NULL) { sepol_log_err("Failed to generate extended permission string"); goto exit; } rule = create_str("(%s %s %s (%s %s (%s)))", 6, flavor, src, tgt, "ioctl", class, perms); } else { new = pdb->p_type_val_to_name[data - 1]; rule = create_str("(%s %s %s %s %s)", 5, flavor, src, tgt, class, new); } if (!rule) { goto exit; } return rule; exit: return NULL; } struct map_avtab_args { struct policydb *pdb; uint32_t flavor; struct strs *strs; }; static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args) { struct map_avtab_args *map_args = args; uint32_t flavor = map_args->flavor; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *rule; int rc = 0; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } exit: return rc; } static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent) { struct map_avtab_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 1000); if (rc != 0) { goto exit; } args.pdb = pdb; args.flavor = flavor; args.strs = strs; rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each_indented(strs, out, indent); exit: strs_free_all(strs); strs_destroy(&strs); return rc; } static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent) { unsigned i; int rc = 0; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent); if (rc != 0) { goto exit; } } exit: if (rc != 0) { sepol_log_err("Error writing avtab rules to CIL\n"); } return rc; } struct map_filename_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) { filename_trans_t *ft = (filename_trans_t *)key; filename_trans_datum_t *datum = data; struct map_filename_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *filename, *new; src = pdb->p_type_val_to_name[ft->stype - 1]; tgt = pdb->p_type_val_to_name[ft->ttype - 1]; class = pdb->p_class_val_to_name[ft->tclass - 1]; filename = ft->name; new = pdb->p_type_val_to_name[datum->otype - 1]; return strs_create_and_add(strs, "(typetransition %s %s %s %s %s)", 5, src, tgt, class, filename, new); } static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb) { struct map_filename_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing filename typetransition rules to CIL\n"); } return rc; } static char *level_to_str(struct policydb *pdb, struct mls_level *level) { ebitmap_t *cats = &level->cat; char *level_str = NULL; char *sens_str = pdb->p_sens_val_to_name[level->sens - 1]; char *cats_str; if (ebitmap_cardinality(cats) > 0) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); level_str = create_str("(%s %s)", 2, sens_str, cats_str); free(cats_str); } else { level_str = create_str("(%s)", 1, sens_str); } return level_str; } static char *range_to_str(struct policydb *pdb, mls_range_t *range) { char *low = NULL; char *high = NULL; char *range_str = NULL; low = level_to_str(pdb, &range->level[0]); if (!low) { goto exit; } high = level_to_str(pdb, &range->level[1]); if (!high) { goto exit; } range_str = create_str("(%s %s)", 2, low, high); exit: free(low); free(high); return range_str; } struct map_range_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) { range_trans_t *rt = (range_trans_t *)key; mls_range_t *mls_range = data; struct map_range_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *range; int rc; src = pdb->p_type_val_to_name[rt->source_type - 1]; tgt = pdb->p_type_val_to_name[rt->target_type - 1]; class = pdb->p_class_val_to_name[rt->target_class - 1]; range = range_to_str(pdb, mls_range); if (!range) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", 4, src, tgt, class, range); free(range); if (rc != 0) { goto exit; } exit: return rc; } static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb) { struct map_range_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing range transition rules to CIL\n"); } return rc; } static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent) { cond_av_list_t *cond_av; avtab_ptr_t node; uint32_t flavor; avtab_key_t *key; avtab_datum_t *datum; struct strs *strs; char *rule; unsigned i; int rc; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { flavor = avtab_flavors[i]; rc = strs_init(&strs, 64); if (rc != 0) { goto exit; } for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) { node = cond_av->node; key = &node->key; datum = &node->datum; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } } strs_sort(strs); strs_write_each_indented(strs, out, indent); strs_free_all(strs); strs_destroy(&strs); } return 0; exit: strs_free_all(strs); strs_destroy(&strs); return rc; } struct cond_data { char *expr; struct cond_node *cond; }; static int cond_node_cmp(const void *a, const void *b) { const struct cond_data *aa = a; const struct cond_data *bb = b; return strcmp(aa->expr, bb->expr); } static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb) { struct cond_data *cond_data; char *expr; struct cond_node *cond; unsigned i, num = 0; int rc = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { num++; } cond_data = calloc(num, sizeof(struct cond_data)); if (!cond_data) { rc = -1; goto exit; } i = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { cond_data[i].cond = cond; expr = cond_expr_to_str(pdb, cond->expr); if (!expr) { num = i; goto exit; } cond_data[i].expr = expr; i++; } qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp); for (i=0; itrue_list != NULL) { sepol_indent(out, 1); sepol_printf(out, "(true\n"); rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2); if (rc != 0) { goto exit; } sepol_indent(out, 1); sepol_printf(out, ")\n"); } if (cond->false_list != NULL) { sepol_indent(out, 1); sepol_printf(out, "(false\n"); rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2); if (rc != 0) { goto exit; } sepol_indent(out, 1); sepol_printf(out, ")\n"); } sepol_printf(out, ")\n"); } exit: if (cond_data) { for (i=0; ip_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ROLE) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_roles.table, child); if (!role) { rc = -1; goto exit; } if (role->bounds > 0) { parent = pdb->p_role_val_to_name[role->bounds - 1]; sepol_printf(out, "(rolebounds %s %s)\n", parent, child); } } for (i=0; ip_roles.table, name); if (!role) { rc = -1; goto exit; } types = &role->types.types; if (types && (ebitmap_cardinality(types) > 0)) { rc = strs_init(&type_strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name); if (rc != 0) { strs_destroy(&type_strs); goto exit; } strs_sort(type_strs); num_types = strs_num_items(type_strs); for (j=0; jp_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type_datum = pdb->type_val_to_struct[i]; if (type_datum->flavor == TYPE_TYPE && type_datum->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; irole_tr; struct strs *strs; char *role, *type, *class, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; type = pdb->p_type_val_to_name[curr->type - 1]; class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", 4, role, type, class, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing role transition rules to CIL\n"); } return rc; } static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb) { role_allow_t *curr = pdb->role_allow; struct strs *strs; char *role, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "(roleallow %s %s)", 2, role, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing role allow rules to CIL\n"); } return rc; } static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb) { struct user_datum *user; struct strs *strs, *role_strs; char *name, *role, *level, *range; struct ebitmap *roles; unsigned i, j, num, num_roles; int rc = 0; rc = strs_init(&strs, pdb->p_users.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_users.nprim; i++) { rc = strs_add(strs, pdb->p_user_val_to_name[i]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } roles = &user->roles.roles; if (roles && (ebitmap_cardinality(roles) > 0)) { rc = strs_init(&role_strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name); if (rc != 0) { strs_destroy(&role_strs); goto exit; } rc = strs_add(role_strs, (char *)DEFAULT_OBJECT); if (rc != 0) { strs_destroy(&role_strs); goto exit; } strs_sort(role_strs); num_roles = strs_num_items(role_strs); for (j=0; jp_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "(userlevel %s ", name); if (pdb->mls) { level = level_to_str(pdb, &user->exp_dfltlevel); if (!level) { rc = -1; goto exit; } sepol_printf(out, "%s", level); free(level); } else { sepol_printf(out, "%s", DEFAULT_LEVEL); } sepol_printf(out, ")\n"); } for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "(userrange %s ", name); if (pdb->mls) { range = range_to_str(pdb, &user->exp_range); if (!range) { rc = -1; goto exit; } sepol_printf(out, "%s", range); free(range); } else { sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL); } sepol_printf(out, ")\n"); } strs_destroy(&strs); exit: if (rc != 0) { sepol_log_err("Error writing user declarations to CIL\n"); } return rc; } static char *context_to_str(struct policydb *pdb, struct context_struct *con) { char *user, *role, *type, *range; char *ctx = NULL; user = pdb->p_user_val_to_name[con->user - 1]; role = pdb->p_role_val_to_name[con->role - 1]; type = pdb->p_type_val_to_name[con->type - 1]; if (pdb->mls) { range = range_to_str(pdb, &con->range); } else { range = create_str("(%s %s)", 2, DEFAULT_LEVEL, DEFAULT_LEVEL); } if (!range) { goto exit; } ctx = create_str("(%s %s %s %s)", 4, user, role, type, range); free(range); exit: return ctx; } static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; char *ctx, *rule; unsigned i; int rc = -1; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = unknown; } ctx = context_to_str(pdb, &isid->context[0]); if (!ctx) { rc = -1; goto exit; } rule = create_str("(sidcontext %s %s)", 2, sid, ctx); free(ctx); if (!rule) { rc = -1; goto exit; } rc = strs_add_at_index(strs, rule, i); if (rc != 0) { free(rule); goto exit; } } strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing sidcontext rules to CIL\n"); } return rc; } static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str, SELINUX_SID_SZ); } static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *fsuse; const char *behavior; char *name, *ctx; int rc = 0; for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } name = fsuse->u.name; ctx = context_to_str(pdb, &fsuse->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing fsuse rules to CIL\n"); } return rc; } static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; struct strs *strs; char *fstype, *name, *ctx; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { fstype = genfs->fstype; name = ocon->u.name; ctx = context_to_str(pdb, &ocon->context[0]); if (!ctx) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "(genfscon %s %s %s)", 3, fstype, name, ctx); free(ctx); if (rc != 0) { goto exit; } } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing genfscon rules to CIL\n"); } return rc; } static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *portcon; const char *protocol; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ char *ctx; int rc = 0; for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "(%u %u)", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &portcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing portcon rules to CIL\n"); } return rc; } static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *netif; char *name, *ctx1, *ctx2; int rc = 0; for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) { name = netif->u.name; ctx1 = context_to_str(pdb, &netif->context[0]); if (!ctx1) { rc = -1; goto exit; } ctx2 = context_to_str(pdb, &netif->context[1]); if (!ctx2) { free(ctx1); rc = -1; goto exit; } sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2); free(ctx1); free(ctx2); } exit: if (rc != 0) { sepol_log_err("Error writing netifcon rules to CIL\n"); } return rc; } static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing nodecon rules to CIL\n"); } return rc; } static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[6]; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing nodecon rules to CIL\n"); } return rc; } static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ char *ctx; int rc = 0; for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL; ibpkeycon = ibpkeycon->next) { memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("ibpkeycon subnet_prefix is invalid: %s", strerror(errno)); rc = -1; goto exit; } low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "(%u %u)", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibpkeycon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ibpkeycon rules to CIL\n"); } return rc; } static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ibendportcon; char port_str[4]; char *ctx; int rc = 0; for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT]; ibendportcon != NULL; ibendportcon = ibendportcon->next) { rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port); if (rc < 0 || rc >= 4) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibendportcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ibendportcon %s %s %s)\n", ibendportcon->u.ibendport.dev_name, port_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ibendportcon rules to CIL\n"); } return rc; } static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ); } static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *pirq; char pirq_str[21]; /* 2^64-1 <= 20 digits */ char *ctx; int rc = 0; for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); if (rc < 0 || rc >= 21) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pirq->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing pirqcon rules to CIL\n"); } return rc; } static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ioport; uint32_t low; uint32_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ char *ctx; int rc = 0; for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { rc = snprintf(low_high_str, 40, "0x%x", low); } else { rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ioport->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ioportcon rules to CIL\n"); } return rc; } static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *iomem; uint64_t low; uint64_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ char *ctx; int rc = 0; for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { rc = snprintf(low_high_str, 40, "0x%"PRIx64, low); } else { rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &iomem->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing iomemcon rules to CIL\n"); } return rc; } static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *pcid; char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */ char *ctx; int rc = 0; for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) { rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device); if (rc < 0 || rc >= 20) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pcid->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing pcidevicecon rules to CIL\n"); } return rc; } static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *dtree; char *name, *ctx; int rc = 0; for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) { name = dtree->u.name; ctx = context_to_str(pdb, &dtree->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(devicetreecon %s %s)\n", name, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing devicetreecon rules to CIL\n"); } return rc; } int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) { struct strs *mls_constraints = NULL; struct strs *non_mls_constraints = NULL; struct strs *mls_validatetrans = NULL; struct strs *non_mls_validatetrans = NULL; int rc = 0; rc = strs_init(&mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&mls_validatetrans, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_validatetrans, 32); if (rc != 0) { goto exit; } if (pdb == NULL) { sepol_log_err("No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { sepol_log_err("Policy is not a kernel policy"); rc = -1; goto exit; } rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; } rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans); if (rc != 0) { goto exit; } rc = write_handle_unknown_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_class_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_sid_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_default_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_mls_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } strs_write_each(mls_constraints, out); strs_write_each(mls_validatetrans, out); rc = write_polcap_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attributes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_attributes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_boolean_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_alias_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_bounds_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attribute_sets_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_permissive_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_avtab_to_cil(out, pdb, 0); if (rc != 0) { goto exit; } rc = write_filename_trans_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } if (pdb->mls) { rc = write_range_trans_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } rc = write_cond_nodes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_transition_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_allow_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_user_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } strs_write_each(non_mls_constraints, out); strs_write_each(non_mls_validatetrans, out); rc = sort_ocontexts(pdb); if (rc != 0) { goto exit; } if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = write_selinux_isid_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_fsuse_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_port_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_netif_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node6_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibpkey_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibendport_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_xen_isid_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pirq_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_ioport_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_iomem_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pcidevice_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_devicetree_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } exit: strs_free_all(mls_constraints); strs_destroy(&mls_constraints); strs_free_all(non_mls_constraints); strs_destroy(&non_mls_constraints); strs_free_all(mls_validatetrans); strs_destroy(&mls_validatetrans); strs_free_all(non_mls_validatetrans); strs_destroy(&non_mls_validatetrans); return rc; } libsepol/src/kernel_to_common.c0100644 0000000 0000000 00000031153 13756670065 015725 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include "kernel_to_common.h" void sepol_log_err(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(stderr, fmt, argptr) < 0) { _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(stderr, "\n") < 0) { _exit(EXIT_FAILURE); } } void sepol_indent(FILE *out, int indent) { if (fprintf(out, "%*s", indent * 4, "") < 0) { sepol_log_err("Failed to write to output"); } } void sepol_printf(FILE *out, const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(out, fmt, argptr) < 0) { sepol_log_err("Failed to write to output"); } va_end(argptr); } __attribute__ ((format(printf, 1, 0))) static char *create_str_helper(const char *fmt, int num, va_list vargs) { va_list vargs2; char *str = NULL; char *s; size_t len; int i, rc; va_copy(vargs2, vargs); len = strlen(fmt) + 1; /* +1 for '\0' */ for (i=0; i= (int)len) { goto exit; } va_end(vargs2); return str; exit: free(str); va_end(vargs2); return NULL; } char *create_str(const char *fmt, int num, ...) { char *str = NULL; va_list vargs; va_start(vargs, num); str = create_str_helper(fmt, num, vargs); va_end(vargs); return str; } int strs_init(struct strs **strs, size_t size) { struct strs *new; *strs = NULL; new = malloc(sizeof(struct strs)); if (!new) { sepol_log_err("Out of memory"); return -1; } new->list = calloc(sizeof(char *), size); if (!new->list) { sepol_log_err("Out of memory"); free(new); return -1; } new->num = 0; new->size = size; *strs = new; return 0; } void strs_destroy(struct strs **strs) { if (!strs || !*strs) { return; } free((*strs)->list); (*strs)->list = NULL; (*strs)->num = 0; (*strs)->size = 0; free(*strs); *strs = NULL; } void strs_free_all(struct strs *strs) { if (!strs) { return; } while (strs->num > 0) { strs->num--; free(strs->list[strs->num]); } } int strs_add(struct strs *strs, char *s) { if (strs->num + 1 > strs->size) { char **new; unsigned i = strs->size; strs->size *= 2; new = realloc(strs->list, sizeof(char *)*strs->size); if (!new) { sepol_log_err("Out of memory"); return -1; } strs->list = new; memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i)); } strs->list[strs->num] = s; strs->num++; return 0; } int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...) { char *str; va_list vargs; int rc; va_start(vargs, num); str = create_str_helper(fmt, num, vargs); va_end(vargs); if (!str) { rc = -1; goto exit; } rc = strs_add(strs, str); if (rc != 0) { free(str); goto exit; } return 0; exit: return rc; } char *strs_remove_last(struct strs *strs) { if (strs->num == 0) { return NULL; } strs->num--; return strs->list[strs->num]; } int strs_add_at_index(struct strs *strs, char *s, unsigned index) { if (index >= strs->size) { char **new; unsigned i = strs->size; while (index >= strs->size) { strs->size *= 2; } new = realloc(strs->list, sizeof(char *)*strs->size); if (!new) { sepol_log_err("Out of memory"); return -1; } strs->list = new; memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i)); } strs->list[index] = s; if (index >= strs->num) { strs->num = index+1; } return 0; } char *strs_read_at_index(struct strs *strs, unsigned index) { if (index >= strs->num) { return NULL; } return strs->list[index]; } static int strs_cmp(const void *a, const void *b) { char *const *aa = a; char *const *bb = b; return strcmp(*aa,*bb); } void strs_sort(struct strs *strs) { if (strs->num == 0) { return; } qsort(strs->list, strs->num, sizeof(char *), strs_cmp); } unsigned strs_num_items(struct strs *strs) { return strs->num; } size_t strs_len_items(struct strs *strs) { unsigned i; size_t len = 0; for (i=0; inum; i++) { if (!strs->list[i]) continue; len += strlen(strs->list[i]); } return len; } char *strs_to_str(struct strs *strs) { char *str = NULL; size_t len = 0; char *p; unsigned i; int rc; if (strs->num == 0) { goto exit; } /* strs->num added because either ' ' or '\0' follows each item */ len = strs_len_items(strs) + strs->num; str = malloc(len); if (!str) { sepol_log_err("Out of memory"); goto exit; } p = str; for (i=0; inum; i++) { if (!strs->list[i]) continue; len = strlen(strs->list[i]); rc = snprintf(p, len+1, "%s", strs->list[i]); if (rc < 0 || rc > (int)len) { free(str); str = NULL; goto exit; } p += len; if (i < strs->num - 1) { *p++ = ' '; } } *p = '\0'; exit: return str; } void strs_write_each(struct strs *strs, FILE *out) { unsigned i; for (i=0; inum; i++) { if (!strs->list[i]) { continue; } sepol_printf(out, "%s\n",strs->list[i]); } } void strs_write_each_indented(struct strs *strs, FILE *out, int indent) { unsigned i; for (i=0; inum; i++) { if (!strs->list[i]) { continue; } sepol_indent(out, indent); sepol_printf(out, "%s\n",strs->list[i]); } } int hashtab_ordered_to_strs(char *key, void *data, void *args) { struct strs *strs = (struct strs *)args; symtab_datum_t *datum = data; return strs_add_at_index(strs, key, datum->value-1); } int ebitmap_to_strs(struct ebitmap *map, struct strs *strs, char **val_to_name) { struct ebitmap_node *node; uint32_t i; int rc; ebitmap_for_each_bit(map, node, i) { if (!ebitmap_get_bit(map, i)) continue; rc = strs_add(strs, val_to_name[i]); if (rc != 0) { return -1; } } return 0; } char *ebitmap_to_str(struct ebitmap *map, char **val_to_name, int sort) { struct strs *strs; char *str = NULL; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(map, strs, val_to_name); if (rc != 0) { goto exit; } if (sort) { strs_sort(strs); } str = strs_to_str(strs); exit: strs_destroy(&strs); return str; } int strs_stack_init(struct strs **stack) { return strs_init(stack, STACK_SIZE); } void strs_stack_destroy(struct strs **stack) { return strs_destroy(stack); } int strs_stack_push(struct strs *stack, char *s) { return strs_add(stack, s); } char *strs_stack_pop(struct strs *stack) { return strs_remove_last(stack); } int strs_stack_empty(struct strs *stack) { return strs_num_items(stack) == 0; } static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2) { uint64_t d1, d2; d1 = h1-l1; d2 = h2-l2; if (d1 < d2) { return -1; } else if (d1 > d2) { return 1; } else { if (l1 < l2) { return -1; } else if (l1 > l2) { return 1; } } return 0; } static int fsuse_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->v.behavior != (*bb)->v.behavior) { if ((*aa)->v.behavior < (*bb)->v.behavior) { return -1; } else { return 1; } } return strcmp((*aa)->u.name, (*bb)->u.name); } static int portcon_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port, (*bb)->u.port.low_port, (*bb)->u.port.high_port); if (rc == 0) { if ((*aa)->u.port.protocol == (*bb)->u.port.protocol) { rc = 0; } else if ((*aa)->u.port.protocol == IPPROTO_TCP) { rc = -1; } else { rc = 1; } } return rc; } static int netif_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return strcmp((*aa)->u.name, (*bb)->u.name); } static int node_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask)); if (rc > 0) { return -1; } else if (rc < 0) { return 1; } return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr)); } static int node6_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask)); if (rc > 0) { return -1; } else if (rc < 0) { return 1; } return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr)); } static int ibpkey_data_cmp(const void *a, const void *b) { int rc; struct ocontext *const *aa = a; struct ocontext *const *bb = b; rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix; if (rc) return rc; return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey, (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey); } static int ibendport_data_cmp(const void *a, const void *b) { int rc; struct ocontext *const *aa = a; struct ocontext *const *bb = b; rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name); if (rc) return rc; return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port; } static int pirq_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->u.pirq < (*bb)->u.pirq) { return -1; } else if ((*aa)->u.pirq > (*bb)->u.pirq) { return 1; } return 0; } static int ioport_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport, (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport); } static int iomem_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem, (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem); } static int pcid_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->u.device < (*bb)->u.device) { return -1; } else if ((*aa)->u.device > (*bb)->u.device) { return 1; } return 0; } static int dtree_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return strcmp((*aa)->u.name, (*bb)->u.name); } static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *)) { struct ocontext *ocon; struct ocontext **data; unsigned i, num; num = 0; for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { num++; } if (num == 0) { return 0; } data = calloc(sizeof(*data), num); if (!data) { sepol_log_err("Out of memory\n"); return -1; } i = 0; for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { data[i] = ocon; i++; } qsort(data, num, sizeof(*data), cmp); *ocons = data[0]; for (i=1; i < num; i++) { data[i-1]->next = data[i]; } data[num-1]->next = NULL; free(data); return 0; } int sort_ocontexts(struct policydb *pdb) { int rc = 0; if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp); if (rc != 0) { goto exit; } } exit: if (rc != 0) { sepol_log_err("Error sorting ocontexts\n"); } return rc; } libsepol/src/kernel_to_common.h0100644 0000000 0000000 00000005651 13756670065 015736 0ustar000000000 0000000 #include #include #include #include #include #define STACK_SIZE 16 #define DEFAULT_LEVEL "systemlow" #define DEFAULT_OBJECT "object_r" // initial sid names aren't actually stored in the pp files, need to a have // a mapping, taken from the linux kernel static const char * const selinux_sid_to_str[] = { "null", "kernel", "security", "unlabeled", "fs", "file", "file_labels", "init", "any_socket", "port", "netif", "netmsg", "node", "igmp_packet", "icmp_socket", "tcp_socket", "sysctl_modprobe", "sysctl", "sysctl_fs", "sysctl_kernel", "sysctl_net", "sysctl_net_unix", "sysctl_vm", "sysctl_dev", "kmod", "policy", "scmp_packet", "devnull", }; #define SELINUX_SID_SZ (sizeof(selinux_sid_to_str)/sizeof(selinux_sid_to_str[0])) static const char * const xen_sid_to_str[] = { "null", "xen", "dom0", "domio", "domxen", "unlabeled", "security", "ioport", "iomem", "irq", "device", "domU", "domDM", }; #define XEN_SID_SZ (sizeof(xen_sid_to_str)/sizeof(xen_sid_to_str[0])) static const uint32_t avtab_flavors[] = { AVTAB_ALLOWED, AVTAB_AUDITALLOW, AVTAB_AUDITDENY, AVTAB_XPERMS_ALLOWED, AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_DONTAUDIT, AVTAB_TRANSITION, AVTAB_MEMBER, AVTAB_CHANGE, }; #define AVTAB_FLAVORS_SZ (sizeof(avtab_flavors)/sizeof(avtab_flavors[0])) struct strs { char **list; unsigned num; size_t size; }; __attribute__ ((format(printf, 1, 2))) void sepol_log_err(const char *fmt, ...); void sepol_indent(FILE *out, int indent); __attribute__ ((format(printf, 2, 3))) void sepol_printf(FILE *out, const char *fmt, ...); __attribute__ ((format(printf, 1, 3))) char *create_str(const char *fmt, int num, ...); int strs_init(struct strs **strs, size_t size); void strs_destroy(struct strs **strs); void strs_free_all(struct strs *strs); int strs_add(struct strs *strs, char *s); __attribute__ ((format(printf, 2, 4))) int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...); char *strs_remove_last(struct strs *strs); int strs_add_at_index(struct strs *strs, char *s, unsigned index); char *strs_read_at_index(struct strs *strs, unsigned index); void strs_sort(struct strs *strs); unsigned strs_num_items(struct strs *strs); size_t strs_len_items(struct strs *strs); char *strs_to_str(struct strs *strs); void strs_write_each(struct strs *strs, FILE *out); void strs_write_each_indented(struct strs *strs, FILE *out, int indent); int hashtab_ordered_to_strs(char *key, void *data, void *args); int ebitmap_to_strs(struct ebitmap *map, struct strs *strs, char **val_to_name); char *ebitmap_to_str(struct ebitmap *map, char **val_to_name, int sort); int strs_stack_init(struct strs **stack); void strs_stack_destroy(struct strs **stack); int strs_stack_push(struct strs *stack, char *s); char *strs_stack_pop(struct strs *stack); int strs_stack_empty(struct strs *stack); int sort_ocontexts(struct policydb *pdb); libsepol/src/kernel_to_conf.c0100644 0000000 0000000 00000177325 13756670065 015376 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include "kernel_to_common.h" static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) { struct cond_expr *curr; struct strs *stack; char *new_val; char *str = NULL; int rc; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { char *val1 = pdb->p_bool_val_to_name[curr->bool - 1]; new_val = create_str("%s", 1, val1); } else { const char *op; uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch(curr->expr_type) { case COND_NOT: op = "!"; num_params = 1; break; case COND_OR: op = "||"; num_params = 2; break; case COND_AND: op = "&&"; num_params = 2; break; case COND_XOR: op = "^"; num_params = 2; break; case COND_EQ: op = "=="; num_params = 2; break; case COND_NEQ: op = "!="; num_params = 2; break; default: sepol_log_err("Unknown conditional operator: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { sepol_log_err("Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { sepol_log_err("Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", 3, val1, op, val2); free(val2); } else { new_val = create_str("%s %s", 2, op, val1); } free(val1); } if (!new_val) { sepol_log_err("Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { sepol_log_err("Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { sepol_log_err("Invalid conditional expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); return NULL; } static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls) { struct constraint_expr *curr; struct strs *stack = NULL; char *new_val = NULL; const char *op; char *str = NULL; int rc; *use_mls = 0; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr; curr = curr->next) { if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) { const char *attr1 = NULL; const char *attr2 = NULL; switch (curr->op) { case CEXPR_EQ: op = "=="; break; case CEXPR_NEQ: op = "!="; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: sepol_log_err("Unknown constraint operator: %i", curr->op); goto exit; } switch (curr->attr) { case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break; case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break; case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break; case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break; case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break; case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break; case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break; case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: sepol_log_err("Unknown constraint attribute: %i", curr->attr); goto exit; } if (curr->attr >= CEXPR_XTARGET) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { new_val = create_str("%s %s %s", 3, attr1, op, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { struct type_set *ts = curr->type_names; names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1); } else if (curr->attr & CEXPR_USER) { names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1); } else if (curr->attr & CEXPR_ROLE) { names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { goto exit; } new_val = create_str("%s %s %s", 3, attr1, op, names); free(names); } } else { uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch (curr->expr_type) { case CEXPR_NOT: op = "not"; num_params = 1; break; case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: sepol_log_err("Unknown constraint expression type: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { sepol_log_err("Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { sepol_log_err("Invalid constraint expression"); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", 3, val1, op, val2); free(val2); } else { new_val = create_str("%s (%s)", 2, op, val1); } free(val1); } if (!new_val) { goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { sepol_log_err("Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { sepol_log_err("Invalid constraint expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); return NULL; } static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, class_datum_t *class, struct constraint_node *constraint_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; struct strs *strs; const char *format_str, *flavor; char *perms, *expr; int is_mls; int rc = 0; for (curr = constraint_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); if (strchr(perms, ' ')) { format_str = "%s %s { %s } %s;"; } else { format_str = "%s %s %s %s"; } if (is_mls) { flavor = "mlsconstrain"; strs = mls_list; } else { flavor = "constrain"; strs = non_mls_list; } rc = strs_create_and_add(strs, format_str, 4, flavor, classkey, perms+1, expr); free(expr); if (rc != 0) { goto exit; } } return 0; exit: sepol_log_err("Error gathering constraint rules\n"); return rc; } static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, struct constraint_node *validatetrans_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; struct strs *strs; const char *flavor; char *expr; int is_mls; int rc = 0; for (curr = validatetrans_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } if (is_mls) { flavor = "mlsvalidatetrans"; strs = mls_list; } else { flavor = "validatetrans"; strs = non_mls_list; } rc = strs_create_and_add(strs, "%s %s %s;", 3, flavor, classkey, expr); free(expr); if (rc != 0) { goto exit; } } exit: return rc; } static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->constraints) { name = pdb->p_class_val_to_name[i]; rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->validatetrans) { name = pdb->p_class_val_to_name[i]; rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int write_handle_unknown_to_conf(FILE *out, struct policydb *pdb) { const char *action; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: action = "deny"; break; case SEPOL_REJECT_UNKNOWN: action = "reject"; break; case SEPOL_ALLOW_UNKNOWN: action = "allow"; break; default: sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } sepol_printf(out, "# handle_unknown %s\n", action); return 0; } static int write_class_decl_rules_to_conf(FILE *out, struct policydb *pdb) { char *name; unsigned i; for (i=0; i < pdb->p_classes.nprim; i++) { name = pdb->p_class_val_to_name[i]; sepol_printf(out, "class %s\n", name); } return 0; } static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; unsigned i; int rc; rc = strs_init(&strs, num_sids+1); if (rc != 0) { goto exit; } for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = strdup(unknown); } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { goto exit; } } for (i=0; itarget_platform == SEPOL_TARGET_SELINUX) { rc = write_sids_to_conf(out, selinux_sid_to_str, SELINUX_SID_SZ, pdb->ocontexts[0]); } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_sids_to_conf(out, xen_sid_to_str, XEN_SID_SZ, pdb->ocontexts[0]); } else { sepol_log_err("Unknown target platform: %i", pdb->target_platform); rc = -1; } return rc; } static char *class_or_common_perms_to_str(symtab_t *permtab) { struct strs *strs; char *perms = NULL; int rc = 0; rc = strs_init(&strs, permtab->nprim); if (rc != 0) { goto exit; } rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs); if (rc != 0) { goto exit; } if (strs_num_items(strs) > 0) { perms = strs_to_str(strs); } exit: strs_destroy(&strs); return perms; } static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb) { class_datum_t *class; common_datum_t *common; int *used; char *name, *perms; unsigned i; int rc = 0; /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { sepol_log_err("Out of memory"); rc = -1; goto exit; } for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; name = class->comkey; if (!name) continue; common = hashtab_search(pdb->p_commons.table, name); if (!common) { rc = -1; free(used); goto exit; } /* Only write common rule once */ if (!used[common->s.value-1]) { perms = class_or_common_perms_to_str(&common->permissions); if (!perms) { rc = -1; free(used); goto exit; } sepol_printf(out, "common %s { %s }\n", name, perms); free(perms); used[common->s.value-1] = 1; } } free(used); /* class */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; name = pdb->p_class_val_to_name[i]; sepol_printf(out, "class %s", name); if (class->comkey) { sepol_printf(out, " inherits %s", class->comkey); } perms = class_or_common_perms_to_str(&class->permissions); if (perms) { sepol_printf(out, " { %s }", perms); free(perms); } sepol_printf(out, "\n"); } exit: if (rc != 0) { sepol_log_err("Error writing class rules to policy.conf\n"); } return rc; } static int write_default_user_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_user) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "default_user { %s } %s;\n", class_name, dft); return 0; } static int write_default_role_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_role) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "default_role { %s } %s;\n", class_name, dft); return 0; } static int write_default_type_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_type) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: sepol_log_err("Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "default_type { %s } %s;\n", class_name, dft); return 0; } static int write_default_range_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_range) { case DEFAULT_SOURCE_LOW: dft = "source low"; break; case DEFAULT_SOURCE_HIGH: dft = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dft = "source low-high"; break; case DEFAULT_TARGET_LOW: dft = "target low"; break; case DEFAULT_TARGET_HIGH: dft = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dft = "target low-high"; break; default: sepol_log_err("Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "default_range { %s } %s;\n", class_name, dft); return 0; } static int write_default_rules_to_conf(FILE *out, struct policydb *pdb) { class_datum_t *class; unsigned i; int rc = 0; /* default_user */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_user != 0) { rc = write_default_user_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_role */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_role != 0) { rc = write_default_role_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_type */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_type != 0) { rc = write_default_type_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } if (!pdb->mls) { return 0; } /* default_range */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class->default_range != 0) { rc = write_default_range_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } exit: if (rc != 0) { sepol_log_err("Error writing default rules to policy.conf\n"); } return rc; } static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args) { level_datum_t *sens = data; struct strs *strs = args; int rc = 0; if (sens->isalias) { rc = strs_add(strs, key); } return rc; } static int write_sensitivity_rules_to_conf(FILE *out, struct policydb *pdb) { level_datum_t *level; struct strs *strs; char **sens_alias_map = NULL; char *name, *prev, *alias; unsigned i, j, num; int rc = 0; rc = strs_init(&strs, pdb->p_levels.nprim); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs); if (rc != 0) { goto exit; } num = strs_num_items(strs); if (num > 0) { sens_alias_map = calloc(sizeof(*sens_alias_map), pdb->p_levels.nprim); if (!sens_alias_map) { rc = -1; goto exit; } /* map aliases to sensitivities */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } j = level->level->sens - 1; if (!sens_alias_map[j]) { sens_alias_map[j] = strdup(name); } else { alias = sens_alias_map[j]; sens_alias_map[j] = create_str("%s %s", 2, alias, name); free(alias); if (!sens_alias_map[j]) { rc = -1; goto exit; } } } } /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (sens_alias_map && sens_alias_map[i]) { alias = sens_alias_map[i]; if (strchr(alias, ' ')) { sepol_printf(out, "sensitivity %s alias { %s };\n", name, alias); } else { sepol_printf(out, "sensitivity %s alias %s;\n", name, alias); } } else { sepol_printf(out, "sensitivity %s;\n", name); } } /* dominance */ sepol_printf(out, "dominance { "); prev = NULL; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, " }\n"); exit: if (sens_alias_map) { for (i=0; i < pdb->p_levels.nprim; i++) { free(sens_alias_map[i]); } free(sens_alias_map); } strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing sensitivity rules to CIL\n"); } return rc; } static int map_category_aliases_to_strs(char *key, void *data, void *args) { cat_datum_t *cat = data; struct strs *strs = args; int rc = 0; if (cat->isalias) { rc = strs_add(strs, key); } return rc; } static int write_category_rules_to_conf(FILE *out, struct policydb *pdb) { cat_datum_t *cat; struct strs *strs; char **cat_alias_map = NULL; char *name, *alias; unsigned i, j, num; int rc = 0; rc = strs_init(&strs, pdb->p_levels.nprim); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs); if (rc != 0) { goto exit; } num = strs_num_items(strs); if (num > 0) { cat_alias_map = calloc(sizeof(*cat_alias_map), pdb->p_cats.nprim); if (!cat_alias_map) { rc = -1; goto exit; } /* map aliases to categories */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } j = cat->s.value - 1; if (!cat_alias_map[j]) { cat_alias_map[j] = strdup(name); } else { alias = cat_alias_map[j]; cat_alias_map[j] = create_str("%s %s", 2, alias, name); free(alias); if (!cat_alias_map[j]) { rc = -1; goto exit; } } } } /* categories */ for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; if (!name) continue; cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } if (cat->isalias) continue; if (cat_alias_map && cat_alias_map[i]) { alias = cat_alias_map[i]; if (strchr(alias, ' ')) { sepol_printf(out, "category %s alias { %s };\n", name, alias); } else { sepol_printf(out, "category %s alias %s;\n", name, alias); } } else { sepol_printf(out, "category %s;\n", name); } } exit: if (cat_alias_map) { for (i=0; i < pdb->p_cats.nprim; i++) { free(cat_alias_map[i]); } free(cat_alias_map); } strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing category rules to policy.conf\n"); } return rc; } static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; size_t len = 0; range = 0; ebitmap_for_each_bit(cats, node, i) { if (!ebitmap_get_bit(cats, i)) continue; if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; len += strlen(val_to_name[start]) + 1; if (range > 1) { len += strlen(val_to_name[i]) + 1; } range = 0; } return len; } static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range, first; char *catsbuf, *p; const char *fmt; char sep; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); catsbuf = malloc(remaining); if (!catsbuf) { goto exit; } p = catsbuf; first = 1; range = 0; ebitmap_for_each_bit(cats, node, i) { if (!ebitmap_get_bit(cats, i)) continue; if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; if (range > 1) { sep = (range == 2) ? ',' : '.'; fmt = first ? "%s%c%s" : ",%s%c%s"; len = snprintf(p, remaining, fmt, val_to_name[start], sep, val_to_name[i]); } else { fmt = first ? "%s" : ",%s"; len = snprintf(p, remaining, fmt, val_to_name[start]); } if (len < 0 || len >= remaining) { goto exit; } p += len; remaining -= len; first = 0; range = 0; } *p = '\0'; return catsbuf; exit: free(catsbuf); return NULL; } static int write_level_rules_to_conf(FILE *out, struct policydb *pdb) { level_datum_t *level; char *name, *cats; unsigned i; int rc = 0; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (ebitmap_cardinality(&level->level->cat) > 0) { cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name); sepol_printf(out, "level %s:%s;\n", name, cats); free(cats); } else { sepol_printf(out, "level %s;\n", name); } } exit: if (rc != 0) { sepol_log_err("Error writing level rules to policy.conf\n"); } return rc; } static int write_mls_rules_to_conf(FILE *out, struct policydb *pdb) { int rc = 0; if (!pdb->mls) { return 0; } rc = write_sensitivity_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_category_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_level_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } exit: if (rc != 0) { sepol_log_err("Error writing mls rules to policy.conf\n"); } return rc; } static int write_polcap_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; struct ebitmap_node *node; const char *name; uint32_t i; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } ebitmap_for_each_bit(&pdb->policycaps, node, i) { if (!ebitmap_get_bit(&pdb->policycaps, i)) continue; name = sepol_polcap_getname(i); if (name == NULL) { sepol_log_err("Unknown policy capability id: %i", i); rc = -1; goto exit; } rc = strs_create_and_add(strs, "policycap %s;", 1, name); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing polcap rules to policy.conf\n"); } return rc; } static int write_type_attributes_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_ATTRIB) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i = 0; i < num; i++) { name = strs_read_at_index(strs, i); if (!name) { rc = -1; goto exit; } sepol_printf(out, "attribute %s;\n", name); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing typeattribute rules to policy.conf\n"); } return rc; } static int write_role_attributes_to_conf(FILE *out, struct policydb *pdb) { role_datum_t *role; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ATTRIB) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; istate ? "true" : "false"; return strs_create_and_add(strs, "bool %s %s;", 2, key, value); } static int write_boolean_decl_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing boolean declarations to policy.conf\n"); } return rc; } static int write_type_decl_rules_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *name; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_TYPE && type->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { alias = pdb->type_val_to_struct[i]; if (!alias->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, name); if (!alias) { rc = -1; goto exit; } type = pdb->p_type_val_to_name[alias->s.value - 1]; sepol_printf(out, "typealias %s %s;\n", type, name); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing type alias rules to policy.conf\n"); } return rc; } static int write_type_bounds_rules_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *parent; char *child; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor == TYPE_TYPE) { if (type->bounds > 0) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, child); if (!type) { rc = -1; goto exit; } parent = pdb->p_type_val_to_name[type->bounds - 1]; sepol_printf(out, "typebounds %s %s;\n", parent, child); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing type bounds rules to policy.conf\n"); } return rc; } static char *attr_strs_to_str(struct strs *strs) { char *str = NULL; size_t len = 0; char *p; unsigned i; int rc; if (strs->num == 0) { goto exit; } /* 2*strs->num - 1 because ", " follows all but last attr (followed by '\0') */ len = strs_len_items(strs) + 2*strs->num - 1; str = malloc(len); if (!str) { sepol_log_err("Out of memory"); goto exit; } p = str; for (i=0; inum; i++) { if (!strs->list[i]) continue; len = strlen(strs->list[i]); rc = snprintf(p, len+1, "%s", strs->list[i]); if (rc < 0 || rc > (int)len) { free(str); str = NULL; goto exit; } p += len; if (i < strs->num - 1) { *p++ = ','; *p++ = ' '; } } *p = '\0'; exit: return str; } static char *attrmap_to_str(struct ebitmap *map, char **val_to_name) { struct strs *strs; char *str = NULL; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(map, strs, val_to_name); if (rc != 0) { goto exit; } strs_sort(strs); str = attr_strs_to_str(strs); exit: strs_destroy(&strs); return str; } static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; ebitmap_t attrmap; char *name, *attrs; unsigned i; int rc; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type->flavor != TYPE_TYPE || !type->primary) continue; if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue; rc = ebitmap_cpy(&attrmap, &pdb->type_attr_map[i]); if (rc != 0) { goto exit; } rc = ebitmap_set_bit(&attrmap, i, 0); if (rc != 0) { ebitmap_destroy(&attrmap); goto exit; } name = pdb->p_type_val_to_name[i]; attrs = attrmap_to_str(&attrmap, pdb->p_type_val_to_name); ebitmap_destroy(&attrmap); if (!attrs) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "typeattribute %s %s;", 2, name, attrs); free(attrs); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing typeattributeset rules to policy.conf\n"); } return rc; } static int write_type_permissive_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; char *name; struct ebitmap_node *node; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } ebitmap_for_each_bit(&pdb->permissive_map, node, i) { if (!ebitmap_get_bit(&pdb->permissive_map, i)) continue; rc = strs_add(strs, pdb->p_type_val_to_name[i-1]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; idata; type_datum_t *type; const char *flavor, *src, *tgt, *class, *perms, *new; char *rule = NULL; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: flavor = "allow"; break; case AVTAB_AUDITALLOW: flavor = "auditallow"; break; case AVTAB_AUDITDENY: flavor = "dontaudit"; data = ~data; break; case AVTAB_XPERMS_ALLOWED: flavor = "allowxperm"; break; case AVTAB_XPERMS_AUDITALLOW: flavor = "auditallowxperm"; break; case AVTAB_XPERMS_DONTAUDIT: flavor = "dontauditxperm"; break; case AVTAB_TRANSITION: flavor = "type_transition"; break; case AVTAB_MEMBER: flavor = "type_member"; break; case AVTAB_CHANGE: flavor = "type_change"; break; default: sepol_log_err("Unknown avtab type: %i", key->specified); goto exit; } src = pdb->p_type_val_to_name[key->source_type - 1]; tgt = pdb->p_type_val_to_name[key->target_type - 1]; if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) { type = pdb->type_val_to_struct[key->source_type - 1]; if (type->flavor != TYPE_ATTRIB) { tgt = "self"; } } class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { perms = sepol_av_to_string(pdb, key->target_class, data); if (perms == NULL) { sepol_log_err("Failed to generate permission string"); goto exit; } rule = create_str("%s %s %s:%s { %s };", 5, flavor, src, tgt, class, perms+1); } else if (key->specified & AVTAB_XPERMS) { perms = sepol_extended_perms_to_string(datum->xperms); if (perms == NULL) { sepol_log_err("Failed to generate extended permission string"); goto exit; } rule = create_str("%s %s %s:%s %s;", 5, flavor, src, tgt, class, perms); } else { new = pdb->p_type_val_to_name[data - 1]; rule = create_str("%s %s %s:%s %s;", 5, flavor, src, tgt, class, new); } if (!rule) { goto exit; } return rule; exit: return NULL; } struct map_avtab_args { struct policydb *pdb; uint32_t flavor; struct strs *strs; }; static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args) { struct map_avtab_args *map_args = args; uint32_t flavor = map_args->flavor; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *rule; int rc = 0; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } exit: return rc; } static int write_avtab_flavor_to_conf(FILE *out, struct policydb *pdb, uint32_t flavor, int indent) { struct map_avtab_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 1000); if (rc != 0) { goto exit; } args.pdb = pdb; args.flavor = flavor; args.strs = strs; rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each_indented(strs, out, indent); exit: strs_free_all(strs); strs_destroy(&strs); return rc; } static int write_avtab_to_conf(FILE *out, struct policydb *pdb, int indent) { unsigned i; int rc = 0; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { rc = write_avtab_flavor_to_conf(out, pdb, avtab_flavors[i], indent); if (rc != 0) { goto exit; } } exit: if (rc != 0) { sepol_log_err("Error writing avtab rules to policy.conf\n"); } return rc; } struct map_filename_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) { filename_trans_t *ft = (filename_trans_t *)key; filename_trans_datum_t *datum = data; struct map_filename_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *filename, *new; src = pdb->p_type_val_to_name[ft->stype - 1]; tgt = pdb->p_type_val_to_name[ft->ttype - 1]; class = pdb->p_class_val_to_name[ft->tclass - 1]; filename = ft->name; new = pdb->p_type_val_to_name[datum->otype - 1]; return strs_create_and_add(strs, "type_transition %s %s:%s %s \"%s\";", 5, src, tgt, class, new, filename); } static int write_filename_trans_rules_to_conf(FILE *out, struct policydb *pdb) { struct map_filename_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing filename typetransition rules to policy.conf\n"); } return rc; } static char *level_to_str(struct policydb *pdb, struct mls_level *level) { ebitmap_t *cats = &level->cat; char *level_str = NULL; char *sens_str = pdb->p_sens_val_to_name[level->sens - 1]; char *cats_str; if (ebitmap_cardinality(cats) > 0) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); level_str = create_str("%s:%s", 2, sens_str, cats_str); free(cats_str); } else { level_str = create_str("%s", 1, sens_str); } return level_str; } static char *range_to_str(struct policydb *pdb, mls_range_t *range) { char *low = NULL; char *high = NULL; char *range_str = NULL; low = level_to_str(pdb, &range->level[0]); if (!low) { goto exit; } high = level_to_str(pdb, &range->level[1]); if (!high) { goto exit; } range_str = create_str("%s - %s", 2, low, high); exit: free(low); free(high); return range_str; } struct map_range_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) { range_trans_t *rt = (range_trans_t *)key; mls_range_t *mls_range = data; struct map_range_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *range; int rc; src = pdb->p_type_val_to_name[rt->source_type - 1]; tgt = pdb->p_type_val_to_name[rt->target_type - 1]; class = pdb->p_class_val_to_name[rt->target_class - 1]; range = range_to_str(pdb, mls_range); if (!range) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "range_transition %s %s:%s %s;", 4, src, tgt, class, range); free(range); if (rc != 0) { goto exit; } exit: return rc; } static int write_range_trans_rules_to_conf(FILE *out, struct policydb *pdb) { struct map_range_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing range transition rules to policy.conf\n"); } return rc; } static int write_cond_av_list_to_conf(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent) { cond_av_list_t *cond_av; avtab_ptr_t node; uint32_t flavor; avtab_key_t *key; avtab_datum_t *datum; struct strs *strs; char *rule; unsigned i; int rc; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { flavor = avtab_flavors[i]; rc = strs_init(&strs, 64); if (rc != 0) { goto exit; } for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) { node = cond_av->node; key = &node->key; datum = &node->datum; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } } strs_sort(strs); strs_write_each_indented(strs, out, indent); strs_free_all(strs); strs_destroy(&strs); } return 0; exit: strs_free_all(strs); strs_destroy(&strs); return rc; } struct cond_data { char *expr; struct cond_node *cond; }; static int cond_node_cmp(const void *a, const void *b) { const struct cond_data *aa = a; const struct cond_data *bb = b; return strcmp(aa->expr, bb->expr); } static int write_cond_nodes_to_conf(FILE *out, struct policydb *pdb) { struct cond_data *cond_data; char *expr; struct cond_node *cond; unsigned i, num; int rc = 0; num = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { num++; } if (num == 0) { return 0; } cond_data = calloc(sizeof(struct cond_data), num); if (!cond_data) { rc = -1; goto exit; } i = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { cond_data[i].cond = cond; expr = cond_expr_to_str(pdb, cond->expr); if (!expr) { num = i; goto exit; } cond_data[i].expr = expr; i++; } qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp); for (i=0; itrue_list != NULL) { rc = write_cond_av_list_to_conf(out, pdb, cond->true_list, 1); if (rc != 0) { goto exit; } } if (cond->false_list != NULL) { sepol_printf(out, "} else {\n"); rc = write_cond_av_list_to_conf(out, pdb, cond->false_list, 1); if (rc != 0) { goto exit; } } sepol_printf(out, "}\n"); } exit: if (cond_data) { for (i=0; ip_roles.nprim); if (rc != 0) { goto exit; } /* Start at 1 to skip object_r */ for (i=1; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ROLE) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_roles.table, name); if (!role) { rc = -1; goto exit; } if (ebitmap_cardinality(&role->types.types) == 0) continue; types = ebitmap_to_str(&role->types.types, pdb->p_type_val_to_name, 1); if (!types) { rc = -1; goto exit; } if (strlen(types) > 900) { p1 = types; while (p1) { p2 = p1; while (p2 - p1 < 600) { p2 = strchr(p2, ' '); if (!p2) break; p2++; } if (p2) { *(p2-1) = '\0'; } sepol_printf(out, "role %s types { %s };\n", name, p1); p1 = p2; } } else { sepol_printf(out, "role %s types { %s };\n", name, types); } free(types); } exit: strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing role declarations to policy.conf\n"); } return rc; } static int write_role_transition_rules_to_conf(FILE *out, struct policydb *pdb) { role_trans_t *curr = pdb->role_tr; struct strs *strs; char *role, *type, *class, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; type = pdb->p_type_val_to_name[curr->type - 1]; class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "role_transition %s %s:%s %s;", 4, role, type, class, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing role transition rules to policy.conf\n"); } return rc; } static int write_role_allow_rules_to_conf(FILE *out, struct policydb *pdb) { role_allow_t *curr = pdb->role_allow; struct strs *strs; char *role, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "allow %s %s;", 2, role, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing role allow rules to policy.conf\n"); } return rc; } static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb) { struct user_datum *user; struct strs *strs; char *name, *roles, *level, *range; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_users.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_users.nprim; i++) { rc = strs_add(strs, pdb->p_user_val_to_name[i]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "user %s", name); if (ebitmap_cardinality(&user->roles.roles) > 0) { roles = ebitmap_to_str(&user->roles.roles, pdb->p_role_val_to_name, 1); if (!roles) { rc = -1; goto exit; } if (strchr(roles, ' ')) { sepol_printf(out, " roles { %s }", roles); } else { sepol_printf(out, " roles %s", roles); } free(roles); } if (pdb->mls) { level = level_to_str(pdb, &user->exp_dfltlevel); if (!level) { rc = -1; goto exit; } sepol_printf(out, " level %s", level); free(level); range = range_to_str(pdb, &user->exp_range); if (!range) { rc = -1; goto exit; } sepol_printf(out, " range %s", range); free(range); } sepol_printf(out, ";\n"); } strs_destroy(&strs); exit: if (rc != 0) { sepol_log_err("Error writing user declarations to policy.conf\n"); } return rc; } static char *context_to_str(struct policydb *pdb, struct context_struct *con) { char *user, *role, *type, *range; char *ctx = NULL; user = pdb->p_user_val_to_name[con->user - 1]; role = pdb->p_role_val_to_name[con->role - 1]; type = pdb->p_type_val_to_name[con->type - 1]; if (pdb->mls) { range = range_to_str(pdb, &con->range); ctx = create_str("%s:%s:%s:%s", 4, user, role, type, range); free(range); } else { ctx = create_str("%s:%s:%s", 3, user, role, type); } return ctx; } static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; char *ctx, *rule; unsigned i; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = unknown; } ctx = context_to_str(pdb, &isid->context[0]); if (!ctx) { rc = -1; goto exit; } rule = create_str("sid %s %s", 2, sid, ctx); free(ctx); if (!rule) { rc = -1; goto exit; } rc = strs_add_at_index(strs, rule, i); if (rc != 0) { free(rule); goto exit; } } strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing sidcontext rules to policy.conf\n"); } return rc; } static int write_selinux_isid_rules_to_conf(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_conf(out, pdb, selinux_sid_to_str, SELINUX_SID_SZ); } static int write_selinux_fsuse_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *fsuse; const char *behavior; char *name, *ctx; int rc = 0; for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } name = fsuse->u.name; ctx = context_to_str(pdb, &fsuse->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "fs_use_%s %s %s;\n", behavior, name, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing fsuse rules to policy.conf\n"); } return rc; } static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; struct strs *strs; char *fstype, *name, *ctx; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { fstype = genfs->fstype; name = ocon->u.name; ctx = context_to_str(pdb, &ocon->context[0]); if (!ctx) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "genfscon %s %s %s", 3, fstype, name, ctx); free(ctx); if (rc != 0) { goto exit; } } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { sepol_log_err("Error writing genfscon rules to policy.conf\n"); } return rc; } static int write_selinux_port_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *portcon; const char *protocol; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "low-high" <= 44 chars */ char *ctx; int rc = 0; for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "%u-%u", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &portcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "portcon %s %s %s\n", protocol, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing portcon rules to policy.conf\n"); } return rc; } static int write_selinux_netif_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *netif; char *name, *ctx1, *ctx2; int rc = 0; for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) { name = netif->u.name; ctx1 = context_to_str(pdb, &netif->context[0]); if (!ctx1) { rc = -1; goto exit; } ctx2 = context_to_str(pdb, &netif->context[1]); if (!ctx2) { free(ctx1); rc = -1; goto exit; } sepol_printf(out, "netifcon %s %s %s\n", name, ctx1, ctx2); free(ctx1); free(ctx2); } exit: if (rc != 0) { sepol_log_err("Error writing netifcon rules to policy.conf\n"); } return rc; } static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "nodecon %s %s %s\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing nodecon rules to policy.conf\n"); } return rc; } static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *node6; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; char *ctx; int rc = 0; for (node6 = pdb->ocontexts[6]; node6 != NULL; node6 = node6->next) { if (inet_ntop(AF_INET6, &node6->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node6->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } ctx = context_to_str(pdb, &node6->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "nodecon %s %s %s\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing nodecon rules to policy.conf\n"); } return rc; } static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "low-high" <= 44 chars */ char *ctx; int rc = 0; for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL; ibpkeycon = ibpkeycon->next) { memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { sepol_log_err("ibpkeycon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "%u-%u", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibpkeycon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ibpkeycon %s %s %s\n", subnet_prefix_str, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ibpkeycon rules to policy.conf\n"); } return rc; } static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ibendportcon; char port_str[4]; char *ctx; int rc = 0; for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT]; ibendportcon != NULL; ibendportcon = ibendportcon->next) { rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port); if (rc < 0 || rc >= 4) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibendportcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ibendportcon %s %s %s\n", ibendportcon->u.ibendport.dev_name, port_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ibendportcon rules to policy.conf\n"); } return rc; } static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str, XEN_SID_SZ); } static int write_xen_pirq_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *pirq; char pirq_str[21]; /* 2^64-1 <= 20 digits */ char *ctx; int rc = 0; for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); if (rc < 0 || rc >= 21) { fprintf(stderr,"error1\n"); rc = -1; goto exit; } ctx = context_to_str(pdb, &pirq->context[0]); if (!ctx) { rc = -1; fprintf(stderr,"error2\n"); goto exit; } sepol_printf(out, "pirqcon %s %s\n", pirq_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing pirqcon rules to policy.conf\n"); } return rc; } static int write_xen_ioport_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ioport; uint32_t low; uint32_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so low-high < 40 chars */ char *ctx; int rc = 0; for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { rc = snprintf(low_high_str, 40, "0x%x", low); } else { rc = snprintf(low_high_str, 40, "0x%x-0x%x", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ioport->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ioportcon %s %s\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing ioportcon rules to policy.conf\n"); } return rc; } static int write_xen_iomem_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *iomem; uint64_t low; uint64_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so low-high < 40 chars */ char *ctx; int rc = 0; for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { rc = snprintf(low_high_str, 40, "0x%"PRIx64, low); } else { rc = snprintf(low_high_str, 40, "0x%"PRIx64"-0x%"PRIx64, low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &iomem->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "iomemcon %s %s\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing iomemcon rules to policy.conf\n"); } return rc; } static int write_xen_pcidevice_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *pcid; char device_str[20]; /* 2^64-1 <= 16 digits (hex) so < 19 chars */ char *ctx; int rc = 0; for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) { rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device); if (rc < 0 || rc >= 20) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pcid->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "pcidevicecon %s %s\n", device_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { sepol_log_err("Error writing pcidevicecon rules to policy.conf\n"); } return rc; } static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *dtree; char *name, *ctx; int rc = 0; for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) { name = dtree->u.name; ctx = context_to_str(pdb, &dtree->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "devicetreecon %s %s\n", name, ctx); free(ctx); } exit: if (rc != 0) { sepol_log_err("Error writing devicetreecon rules to policy.conf\n"); } return rc; } int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb) { struct strs *mls_constraints = NULL; struct strs *non_mls_constraints = NULL; struct strs *mls_validatetrans = NULL; struct strs *non_mls_validatetrans = NULL; int rc = 0; rc = strs_init(&mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&mls_validatetrans, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_validatetrans, 32); if (rc != 0) { goto exit; } if (pdb == NULL) { sepol_log_err("No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { sepol_log_err("Policy is not a kernel policy"); rc = -1; goto exit; } rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; } rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans); if (rc != 0) { goto exit; } rc = write_handle_unknown_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_class_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_sid_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_class_and_common_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_default_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_mls_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } strs_write_each(mls_constraints, out); strs_write_each(mls_validatetrans, out); rc = write_polcap_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attributes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_attributes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_boolean_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_alias_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_bounds_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attribute_sets_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_permissive_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_avtab_to_conf(out, pdb, 0); if (rc != 0) { goto exit; } write_filename_trans_rules_to_conf(out, pdb); if (pdb->mls) { rc = write_range_trans_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } rc = write_cond_nodes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_transition_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_allow_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_user_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } strs_write_each(non_mls_constraints, out); strs_write_each(non_mls_validatetrans, out); rc = sort_ocontexts(pdb); if (rc != 0) { goto exit; } if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = write_selinux_isid_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_fsuse_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_port_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_netif_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node6_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibpkey_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibendport_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_xen_isid_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pirq_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_iomem_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_ioport_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pcidevice_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_devicetree_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } exit: strs_free_all(mls_constraints); strs_destroy(&mls_constraints); strs_free_all(non_mls_constraints); strs_destroy(&non_mls_constraints); strs_free_all(mls_validatetrans); strs_destroy(&mls_validatetrans); strs_free_all(non_mls_validatetrans); strs_destroy(&non_mls_validatetrans); return rc; } libsepol/src/libsepol.map.in0100644 0000000 0000000 00000003011 13756670065 015134 0ustar000000000 0000000 LIBSEPOL_1.0 { global: expand_module_avrules; sepol_module_package_*; sepol_link_modules; sepol_expand_module; sepol_link_packages; sepol_bool_*; sepol_genbools*; sepol_context_*; sepol_mls_*; sepol_check_context; sepol_iface_*; sepol_port_*; sepol_ibpkey_*; sepol_ibendport_*; sepol_node_*; sepol_user_*; sepol_genusers; sepol_set_delusers; sepol_msg_*; sepol_debug; sepol_handle_*; sepol_policydb_*; sepol_set_policydb_from_file; sepol_policy_kern_*; sepol_policy_file_*; sepol_get_disable_dontaudit; sepol_set_disable_dontaudit; sepol_set_expand_consume_base; sepol_get_preserve_tunables; sepol_set_preserve_tunables; cil_db_init; cil_set_disable_dontaudit; cil_set_disable_neverallow; cil_set_preserve_tunables; cil_set_handle_unknown; cil_db_destroy; cil_add_file; cil_compile; cil_build_policydb; cil_userprefixes_to_string; cil_selinuxusers_to_string; cil_filecons_to_string; cil_set_log_level; cil_set_log_handler; cil_set_malloc_error_handler; local: *; }; LIBSEPOL_1.1 { global: cil_build_policydb; cil_compile; cil_userprefixes_to_string; cil_selinuxusers_to_string; cil_filecons_to_string; cil_set_target_platform; cil_set_policy_version; cil_set_mls; cil_set_attrs_expand_generated; cil_set_attrs_expand_size; cil_set_multiple_decls; cil_write_policy_conf; sepol_ppfile_to_module_package; sepol_module_package_to_cil; sepol_module_policydb_to_cil; sepol_kernel_policydb_to_cil; sepol_kernel_policydb_to_conf; sepol_polcap_getnum; sepol_polcap_getname; } LIBSEPOL_1.0; libsepol/src/libsepol.pc.in0100644 0000000 0000000 00000000361 13756670065 014766 0ustar000000000 0000000 prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ Name: libsepol Description: SELinux policy library Version: @VERSION@ URL: http://userspace.selinuxproject.org/ Libs: -L${libdir} -lsepol Cflags: -I${includedir} libsepol/src/link.c0100644 0000000 0000000 00000214403 13756670065 013331 0ustar000000000 0000000 /* Authors: Karl MacMillan * Joshua Brindle * Jason Tang * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #undef min #define min(a,b) (((a) < (b)) ? (a) : (b)) typedef struct policy_module { policydb_t *policy; uint32_t num_decls; uint32_t *map[SYM_NUM]; uint32_t *avdecl_map; uint32_t **perm_map; uint32_t *perm_map_len; /* a pointer to within the base module's avrule_block chain to * where this module's global now resides */ avrule_block_t *base_global; } policy_module_t; typedef struct link_state { int verbose; policydb_t *base; avrule_block_t *last_avrule_block, *last_base_avrule_block; uint32_t next_decl_id, current_decl_id; /* temporary variables, used during hashtab_map() calls */ policy_module_t *cur; char *cur_mod_name; avrule_decl_t *dest_decl; class_datum_t *src_class, *dest_class; char *dest_class_name; char dest_class_req; /* flag indicating the class was not declared */ uint32_t symbol_num; /* used to report the name of the module if dependancy error occurs */ policydb_t **decl_to_mod; /* error reporting fields */ sepol_handle_t *handle; } link_state_t; typedef struct missing_requirement { uint32_t symbol_type; uint32_t symbol_value; uint32_t perm_value; } missing_requirement_t; static const char *symtab_names[SYM_NUM] = { "common", "class", "role", "type/attribute", "user", "bool", "level", "category" }; /* Deallocates all elements within a module, but NOT the policydb_t * structure within, as well as the pointer itself. */ static void policy_module_destroy(policy_module_t * mod) { unsigned int i; if (mod == NULL) { return; } for (i = 0; i < SYM_NUM; i++) { free(mod->map[i]); } for (i = 0; mod->perm_map != NULL && i < mod->policy->p_classes.nprim; i++) { free(mod->perm_map[i]); } free(mod->perm_map); free(mod->perm_map_len); free(mod->avdecl_map); free(mod); } /***** functions that copy identifiers from a module to base *****/ /* Note: there is currently no scoping for permissions, which causes some * strange side-effects. The current approach is this: * * a) perm is required and the class _and_ perm are declared in base: only add a mapping. * b) perm is required and the class and perm are _not_ declared in base: simply add the permissions * to the object class. This means that the requirements for the decl are the union of the permissions * required for all decls, but who cares. * c) perm is required, the class is declared in base, but the perm is not present. Nothing we can do * here because we can't mark a single permission as required, so we bail with a requirement error * _even_ if we are in an optional. * * A is correct behavior, b is wrong but not too bad, c is totall wrong for optionals. Fixing this requires * a format change. */ static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *perm_id = key, *new_id = NULL; perm_datum_t *perm, *new_perm = NULL, *dest_perm; link_state_t *state = (link_state_t *) data; class_datum_t *src_class = state->src_class; class_datum_t *dest_class = state->dest_class; policy_module_t *mod = state->cur; uint32_t sclassi = src_class->s.value - 1; int ret; perm = (perm_datum_t *) datum; dest_perm = hashtab_search(dest_class->permissions.table, perm_id); if (dest_perm == NULL && dest_class->comdatum != NULL) { dest_perm = hashtab_search(dest_class->comdatum->permissions.table, perm_id); } if (dest_perm == NULL) { /* If the object class was not declared in the base, add the perm * to the object class. */ if (state->dest_class_req) { /* If the class was required (not declared), insert the new permission */ new_id = strdup(perm_id); if (new_id == NULL) { ERR(state->handle, "Memory error"); ret = SEPOL_ERR; goto err; } new_perm = (perm_datum_t *) calloc(1, sizeof(perm_datum_t)); if (new_perm == NULL) { ERR(state->handle, "Memory error"); ret = SEPOL_ERR; goto err; } ret = hashtab_insert(dest_class->permissions.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_perm); if (ret) { ERR(state->handle, "could not insert permission into class\n"); goto err; } new_perm->s.value = dest_class->permissions.nprim + 1; dest_perm = new_perm; } else { /* this is case c from above */ ERR(state->handle, "Module %s depends on permission %s in class %s, not satisfied", state->cur_mod_name, perm_id, state->dest_class_name); return SEPOL_EREQ; } } /* build the mapping for permissions encompassing this class. * unlike symbols, the permission map translates between * module permission bit to target permission bit. that bit * may have originated from the class -or- it could be from * the class's common parent.*/ if (perm->s.value > mod->perm_map_len[sclassi]) { uint32_t *newmap = calloc(perm->s.value, sizeof(*newmap)); if (newmap == NULL) { ERR(state->handle, "Out of memory!"); return -1; } memcpy(newmap, mod->perm_map[sclassi], mod->perm_map_len[sclassi] * sizeof(*newmap)); free(mod->perm_map[sclassi]); mod->perm_map[sclassi] = newmap; mod->perm_map_len[sclassi] = perm->s.value; } mod->perm_map[sclassi][perm->s.value - 1] = dest_perm->s.value; return 0; err: free(new_id); free(new_perm); return ret; } static int class_copy_default_new_object(link_state_t *state, class_datum_t *olddatum, class_datum_t *newdatum) { if (olddatum->default_user) { if (newdatum->default_user && olddatum->default_user != newdatum->default_user) { ERR(state->handle, "Found conflicting default user definitions"); return SEPOL_ENOTSUP; } newdatum->default_user = olddatum->default_user; } if (olddatum->default_role) { if (newdatum->default_role && olddatum->default_role != newdatum->default_role) { ERR(state->handle, "Found conflicting default role definitions"); return SEPOL_ENOTSUP; } newdatum->default_role = olddatum->default_role; } if (olddatum->default_type) { if (newdatum->default_type && olddatum->default_type != newdatum->default_type) { ERR(state->handle, "Found conflicting default type definitions"); return SEPOL_ENOTSUP; } newdatum->default_type = olddatum->default_type; } if (olddatum->default_range) { if (newdatum->default_range && olddatum->default_range != newdatum->default_range) { ERR(state->handle, "Found conflicting default range definitions"); return SEPOL_ENOTSUP; } newdatum->default_range = olddatum->default_range; } return 0; } static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key, *new_id = NULL; class_datum_t *cladatum, *new_class = NULL; link_state_t *state = (link_state_t *) data; scope_datum_t *scope = NULL; int ret; cladatum = (class_datum_t *) datum; state->dest_class_req = 0; new_class = hashtab_search(state->base->p_classes.table, id); /* If there is not an object class already in the base symtab that means * that either a) a module is trying to declare a new object class (which * the compiler should prevent) or b) an object class was required that is * not in the base. */ if (new_class == NULL) { scope = hashtab_search(state->cur->policy->p_classes_scope.table, id); if (scope == NULL) { ret = SEPOL_ERR; goto err; } if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not yet declare new classes.", state->cur_mod_name); ret = SEPOL_ENOTSUP; goto err; } else { /* It would be nice to error early here because the requirement is * not met, but we cannot because the decl might be optional (in which * case we should record the requirement so that it is just turned * off). Note: this will break horribly if modules can declare object * classes because the class numbers will be all wrong (i.e., they * might be assigned in the order they were required rather than the * current scheme which ensures correct numbering by ordering the * declarations properly). This can't be fixed until some infrastructure * for querying the object class numbers is in place. */ state->dest_class_req = 1; new_class = (class_datum_t *) calloc(1, sizeof(class_datum_t)); if (new_class == NULL) { ERR(state->handle, "Memory error\n"); ret = SEPOL_ERR; goto err; } if (symtab_init (&new_class->permissions, PERM_SYMTAB_SIZE)) { ret = SEPOL_ERR; goto err; } new_id = strdup(id); if (new_id == NULL) { ERR(state->handle, "Memory error\n"); symtab_destroy(&new_class->permissions); ret = SEPOL_ERR; goto err; } ret = hashtab_insert(state->base->p_classes.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_class); if (ret) { ERR(state->handle, "could not insert new class into symtab"); symtab_destroy(&new_class->permissions); goto err; } new_class->s.value = ++(state->base->p_classes.nprim); } } state->cur->map[SYM_CLASSES][cladatum->s.value - 1] = new_class->s.value; /* copy permissions */ state->src_class = cladatum; state->dest_class = new_class; state->dest_class_name = (char *)key; /* copy default new object rules */ ret = class_copy_default_new_object(state, cladatum, new_class); if (ret) return ret; ret = hashtab_map(cladatum->permissions.table, permission_copy_callback, state); if (ret != 0) { return ret; } return 0; err: free(new_class); free(new_id); return ret; } static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; role_datum_t *role, *base_role, *new_role = NULL; link_state_t *state = (link_state_t *) data; role = (role_datum_t *) datum; base_role = hashtab_search(state->base->p_roles.table, id); if (base_role != NULL) { /* role already exists. check that it is what this * module expected. duplicate declarations (e.g., two * modules both declare role foo_r) is checked during * scope_copy_callback(). */ if (role->flavor == ROLE_ATTRIB && base_role->flavor != ROLE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a role attribute, but it was already declared as a regular role.", state->cur_mod_name, id); return -1; } else if (role->flavor != ROLE_ATTRIB && base_role->flavor == ROLE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a regular role, but it was already declared as a role attribute.", state->cur_mod_name, id); return -1; } } else { if (state->verbose) INFO(state->handle, "copying role %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_role = (role_datum_t *) malloc(sizeof(*new_role))) == NULL) { goto cleanup; } role_datum_init(new_role); /* new_role's dominates, types and roles field will be copied * during role_fix_callback() */ new_role->flavor = role->flavor; new_role->s.value = state->base->p_roles.nprim + 1; ret = hashtab_insert(state->base->p_roles.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_role); if (ret) { goto cleanup; } state->base->p_roles.nprim++; base_role = new_role; } if (state->dest_decl) { new_id = NULL; if ((new_role = malloc(sizeof(*new_role))) == NULL) { goto cleanup; } role_datum_init(new_role); new_role->flavor = base_role->flavor; new_role->s.value = base_role->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_roles.table, new_id, new_role)) { goto cleanup; } state->dest_decl->p_roles.nprim++; } state->cur->map[SYM_ROLES][role->s.value - 1] = base_role->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); role_datum_destroy(new_role); free(new_id); free(new_role); return -1; } /* Copy types and attributes from a module into the base module. The * attributes are copied, but the types that make up this attribute * are delayed type_fix_callback(). */ static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; type_datum_t *type, *base_type, *new_type = NULL; link_state_t *state = (link_state_t *) data; type = (type_datum_t *) datum; if ((type->flavor == TYPE_TYPE && !type->primary) || type->flavor == TYPE_ALIAS) { /* aliases are handled later, in alias_copy_callback() */ return 0; } base_type = hashtab_search(state->base->p_types.table, id); if (base_type != NULL) { /* type already exists. check that it is what this * module expected. duplicate declarations (e.g., two * modules both declare type foo_t) is checked during * scope_copy_callback(). */ if (type->flavor == TYPE_ATTRIB && base_type->flavor != TYPE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be an attribute, but it was already declared as a type.", state->cur_mod_name, id); return -1; } else if (type->flavor != TYPE_ATTRIB && base_type->flavor == TYPE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a type, but it was already declared as an attribute.", state->cur_mod_name, id); return -1; } base_type->flags |= type->flags; } else { if (state->verbose) INFO(state->handle, "copying type %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_type = (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } new_type->primary = type->primary; new_type->flags = type->flags; new_type->flavor = type->flavor; /* for attributes, the writing of new_type->types is done in type_fix_callback() */ new_type->s.value = state->base->p_types.nprim + 1; ret = hashtab_insert(state->base->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_type); if (ret) { goto cleanup; } state->base->p_types.nprim++; base_type = new_type; } if (state->dest_decl) { new_id = NULL; if ((new_type = calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } new_type->primary = type->primary; new_type->flavor = type->flavor; new_type->flags = type->flags; new_type->s.value = base_type->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_types.table, new_id, new_type)) { goto cleanup; } state->dest_decl->p_types.nprim++; } state->cur->map[SYM_TYPES][type->s.value - 1] = base_type->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); free(new_id); free(new_type); return -1; } static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; user_datum_t *user, *base_user, *new_user = NULL; link_state_t *state = (link_state_t *) data; user = (user_datum_t *) datum; base_user = hashtab_search(state->base->p_users.table, id); if (base_user == NULL) { if (state->verbose) INFO(state->handle, "copying user %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_user = (user_datum_t *) malloc(sizeof(*new_user))) == NULL) { goto cleanup; } user_datum_init(new_user); /* new_users's roles and MLS fields will be copied during user_fix_callback(). */ new_user->s.value = state->base->p_users.nprim + 1; ret = hashtab_insert(state->base->p_users.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_user); if (ret) { goto cleanup; } state->base->p_users.nprim++; base_user = new_user; } if (state->dest_decl) { new_id = NULL; if ((new_user = malloc(sizeof(*new_user))) == NULL) { goto cleanup; } user_datum_init(new_user); new_user->s.value = base_user->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_users.table, new_id, new_user)) { goto cleanup; } state->dest_decl->p_users.nprim++; } state->cur->map[SYM_USERS][user->s.value - 1] = base_user->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); user_datum_destroy(new_user); free(new_id); free(new_user); return -1; } static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; cond_bool_datum_t *booldatum, *base_bool, *new_bool = NULL; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; booldatum = (cond_bool_datum_t *) datum; base_bool = hashtab_search(state->base->p_bools.table, id); if (base_bool == NULL) { if (state->verbose) INFO(state->handle, "copying boolean %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_bool = (cond_bool_datum_t *) malloc(sizeof(*new_bool))) == NULL) { goto cleanup; } new_bool->s.value = state->base->p_bools.nprim + 1; ret = hashtab_insert(state->base->p_bools.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_bool); if (ret) { goto cleanup; } state->base->p_bools.nprim++; base_bool = new_bool; base_bool->flags = booldatum->flags; base_bool->state = booldatum->state; } else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) != (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) { /* A mismatch between boolean/tunable declaration * and usage(for example a boolean used in the * tunable_policy() or vice versa). * * This is not allowed and bail out with errors */ ERR(state->handle, "%s: Mismatch between boolean/tunable definition " "and usage for %s", state->cur_mod_name, id); return -1; } /* Get the scope info for this boolean to see if this is the declaration, * if so set the state */ scope = hashtab_search(state->cur->policy->p_bools_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { base_bool->state = booldatum->state; /* Only the declaration rather than requirement * decides if it is a boolean or tunable. */ base_bool->flags = booldatum->flags; } state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); cond_destroy_bool(new_id, new_bool, NULL); return -1; } static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; level_datum_t *level, *base_level; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; level = (level_datum_t *) datum; base_level = hashtab_search(state->base->p_levels.table, id); if (!base_level) { scope = hashtab_search(state->cur->policy->p_sens_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not declare new sensitivities.", state->cur_mod_name); return SEPOL_ENOTSUP; } else if (scope->scope == SCOPE_REQ) { /* unmet requirement */ ERR(state->handle, "%s: Sensitivity %s not declared by base.", state->cur_mod_name, id); return SEPOL_ENOTSUP; } else { ERR(state->handle, "%s: has an unknown scope: %d\n", state->cur_mod_name, scope->scope); return SEPOL_ENOTSUP; } } state->cur->map[SYM_LEVELS][level->level->sens - 1] = base_level->level->sens; return 0; } static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; cat_datum_t *cat, *base_cat; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; cat = (cat_datum_t *) datum; base_cat = hashtab_search(state->base->p_cats.table, id); if (!base_cat) { scope = hashtab_search(state->cur->policy->p_cat_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not declare new categories.", state->cur_mod_name); return SEPOL_ENOTSUP; } else if (scope->scope == SCOPE_REQ) { /* unmet requirement */ ERR(state->handle, "%s: Category %s not declared by base.", state->cur_mod_name, id); return SEPOL_ENOTSUP; } else { /* unknown scope? malformed policy? */ ERR(state->handle, "%s: has an unknown scope: %d\n", state->cur_mod_name, scope->scope); return SEPOL_ENOTSUP; } } state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value; return 0; } static int (*copy_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, class_copy_callback, role_copy_callback, type_copy_callback, user_copy_callback, bool_copy_callback, sens_copy_callback, cat_copy_callback}; /* * The boundaries have to be copied after the types/roles/users are copied, * because it refers hashtab to lookup destinated objects. */ static int type_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; type_datum_t *type = (type_datum_t *) datum; type_datum_t *dest; uint32_t bounds_val; if (!type->bounds) return 0; bounds_val = state->cur->map[SYM_TYPES][type->bounds - 1]; dest = hashtab_search(state->base->p_types.table, key); if (!dest) { ERR(state->handle, "Type lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int role_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; role_datum_t *role = (role_datum_t *) datum; role_datum_t *dest; uint32_t bounds_val; if (!role->bounds) return 0; bounds_val = state->cur->map[SYM_ROLES][role->bounds - 1]; dest = hashtab_search(state->base->p_roles.table, key); if (!dest) { ERR(state->handle, "Role lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int user_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; user_datum_t *user = (user_datum_t *) datum; user_datum_t *dest; uint32_t bounds_val; if (!user->bounds) return 0; bounds_val = state->cur->map[SYM_USERS][user->bounds - 1]; dest = hashtab_search(state->base->p_users.table, key); if (!dest) { ERR(state->handle, "User lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } /* The aliases have to be copied after the types and attributes to be * certain that the base symbol table will have the type that the * alias refers. Otherwise, we won't be able to find the type value * for the alias. We can't depend on the declaration ordering because * of the hash table. */ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key, *new_id = NULL, *target_id; type_datum_t *type, *base_type, *new_type = NULL, *target_type; link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; int primval; type = (type_datum_t *) datum; /* there are 2 kinds of aliases. Ones with their own value (TYPE_ALIAS) * and ones with the value of their primary (TYPE_TYPE && type->primary = 0) */ if (! (type->flavor == TYPE_ALIAS || (type->flavor == TYPE_TYPE && !type->primary))) { /* ignore types and attributes -- they were handled in * type_copy_callback() */ return 0; } if (type->flavor == TYPE_ALIAS) primval = type->primary; else primval = type->s.value; target_id = mod->policy->p_type_val_to_name[primval - 1]; target_type = hashtab_search(state->base->p_types.table, target_id); if (target_type == NULL) { ERR(state->handle, "%s: Could not find type %s for alias %s.", state->cur_mod_name, target_id, id); return -1; } if (!strcmp(id, target_id)) { ERR(state->handle, "%s: Self aliasing of %s.", state->cur_mod_name, id); return -1; } target_type->flags |= type->flags; base_type = hashtab_search(state->base->p_types.table, id); if (base_type == NULL) { if (state->verbose) INFO(state->handle, "copying alias %s", id); if ((new_type = (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } /* the linked copy always has TYPE_ALIAS style aliases */ new_type->primary = target_type->s.value; new_type->flags = target_type->flags; new_type->flavor = TYPE_ALIAS; new_type->s.value = state->base->p_types.nprim + 1; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->base->p_types.table, new_id, new_type)) { goto cleanup; } state->base->p_types.nprim++; base_type = new_type; } else { /* if this already exists and isn't an alias it was required by another module (or base) * and inserted into the hashtable as a type, fix it up now */ if (base_type->flavor == TYPE_ALIAS) { /* error checking */ assert(base_type->primary == target_type->s.value); assert(base_type->primary == mod->map[SYM_TYPES][primval - 1]); assert(mod->map[SYM_TYPES][type->s.value - 1] == base_type->primary); return 0; } if (base_type->flavor == TYPE_ATTRIB) { ERR(state->handle, "%s is an alias of an attribute, not allowed", id); return -1; } base_type->flavor = TYPE_ALIAS; base_type->primary = target_type->s.value; base_type->flags |= target_type->flags; } /* the aliases map points from its value to its primary so when this module * references this type the value it gets back from the map is the primary */ mod->map[SYM_TYPES][type->s.value - 1] = base_type->primary; return 0; cleanup: ERR(state->handle, "Out of memory!"); free(new_id); free(new_type); return -1; } /*********** callbacks that fix bitmaps ***********/ static int type_set_convert(type_set_t * types, type_set_t * dst, policy_module_t * mod, link_state_t * state __attribute__ ((unused))) { unsigned int i; ebitmap_node_t *tnode; ebitmap_for_each_bit(&types->types, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { assert(mod->map[SYM_TYPES][i]); if (ebitmap_set_bit (&dst->types, mod->map[SYM_TYPES][i] - 1, 1)) { goto cleanup; } } } ebitmap_for_each_bit(&types->negset, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { assert(mod->map[SYM_TYPES][i]); if (ebitmap_set_bit (&dst->negset, mod->map[SYM_TYPES][i] - 1, 1)) { goto cleanup; } } } dst->flags = types->flags; return 0; cleanup: return -1; } /* OR 2 typemaps together and at the same time map the src types to * the correct values in the dst typeset. */ static int type_set_or_convert(type_set_t * types, type_set_t * dst, policy_module_t * mod, link_state_t * state) { type_set_t ts_tmp; type_set_init(&ts_tmp); if (type_set_convert(types, &ts_tmp, mod, state) == -1) { goto cleanup; } if (type_set_or_eq(dst, &ts_tmp)) { goto cleanup; } type_set_destroy(&ts_tmp); return 0; cleanup: ERR(state->handle, "Out of memory!"); type_set_destroy(&ts_tmp); return -1; } static int role_set_or_convert(role_set_t * roles, role_set_t * dst, policy_module_t * mod, link_state_t * state) { unsigned int i; ebitmap_t tmp; ebitmap_node_t *rnode; ebitmap_init(&tmp); ebitmap_for_each_bit(&roles->roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { assert(mod->map[SYM_ROLES][i]); if (ebitmap_set_bit (&tmp, mod->map[SYM_ROLES][i] - 1, 1)) { goto cleanup; } } } if (ebitmap_union(&dst->roles, &tmp)) { goto cleanup; } dst->flags |= roles->flags; ebitmap_destroy(&tmp); return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp); return -1; } static int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst, policy_module_t * mod, link_state_t * state) { mls_semantic_cat_t *src_cat, *new_cat; if (!mod->policy->mls) return 0; /* Required not declared. */ if (!src->sens) return 0; assert(mod->map[SYM_LEVELS][src->sens - 1]); dst->sens = mod->map[SYM_LEVELS][src->sens - 1]; for (src_cat = src->cat; src_cat; src_cat = src_cat->next) { new_cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!new_cat) { ERR(state->handle, "Out of memory"); return -1; } mls_semantic_cat_init(new_cat); new_cat->next = dst->cat; dst->cat = new_cat; assert(mod->map[SYM_CATS][src_cat->low - 1]); dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1]; assert(mod->map[SYM_CATS][src_cat->high - 1]); dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1]; } return 0; } static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * dst, policy_module_t * mod, link_state_t * state) { int ret; ret = mls_level_convert(&src->level[0], &dst->level[0], mod, state); if (ret) return ret; ret = mls_level_convert(&src->level[1], &dst->level[1], mod, state); if (ret) return ret; return 0; } static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { unsigned int i; char *id = key; role_datum_t *role, *dest_role = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; ebitmap_node_t *rnode; hashtab_t role_tab; role = (role_datum_t *) datum; if (state->dest_decl == NULL) role_tab = state->base->p_roles.table; else role_tab = state->dest_decl->p_roles.table; dest_role = hashtab_search(role_tab, id); assert(dest_role != NULL); if (state->verbose) { INFO(state->handle, "fixing role %s", id); } ebitmap_init(&e_tmp); ebitmap_for_each_bit(&role->dominates, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { assert(mod->map[SYM_ROLES][i]); if (ebitmap_set_bit (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { goto cleanup; } } } if (ebitmap_union(&dest_role->dominates, &e_tmp)) { goto cleanup; } if (type_set_or_convert(&role->types, &dest_role->types, mod, state)) { goto cleanup; } ebitmap_destroy(&e_tmp); if (role->flavor == ROLE_ATTRIB) { ebitmap_init(&e_tmp); ebitmap_for_each_bit(&role->roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { assert(mod->map[SYM_ROLES][i]); if (ebitmap_set_bit (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { goto cleanup; } } } if (ebitmap_union(&dest_role->roles, &e_tmp)) { goto cleanup; } ebitmap_destroy(&e_tmp); } return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&e_tmp); return -1; } static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { unsigned int i; char *id = key; type_datum_t *type, *new_type = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; ebitmap_node_t *tnode; symtab_t *typetab; type = (type_datum_t *) datum; if (state->dest_decl == NULL) typetab = &state->base->p_types; else typetab = &state->dest_decl->p_types; /* only fix attributes */ if (type->flavor != TYPE_ATTRIB) { return 0; } new_type = hashtab_search(typetab->table, id); assert(new_type != NULL && new_type->flavor == TYPE_ATTRIB); if (state->verbose) { INFO(state->handle, "fixing attribute %s", id); } ebitmap_init(&e_tmp); ebitmap_for_each_bit(&type->types, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { assert(mod->map[SYM_TYPES][i]); if (ebitmap_set_bit (&e_tmp, mod->map[SYM_TYPES][i] - 1, 1)) { goto cleanup; } } } if (ebitmap_union(&new_type->types, &e_tmp)) { goto cleanup; } ebitmap_destroy(&e_tmp); return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&e_tmp); return -1; } static int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; user_datum_t *user, *new_user = NULL; link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; symtab_t *usertab; user = (user_datum_t *) datum; if (state->dest_decl == NULL) usertab = &state->base->p_users; else usertab = &state->dest_decl->p_users; new_user = hashtab_search(usertab->table, id); assert(new_user != NULL); if (state->verbose) { INFO(state->handle, "fixing user %s", id); } if (role_set_or_convert(&user->roles, &new_user->roles, mod, state)) { goto cleanup; } if (mls_range_convert(&user->range, &new_user->range, mod, state)) goto cleanup; if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod, state)) goto cleanup; return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } static int (*fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback, NULL, NULL, NULL}; /*********** functions that copy AV rules ***********/ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, policy_module_t * module, link_state_t * state) { unsigned int i; avrule_t *cur, *new_rule = NULL, *tail; class_perm_node_t *cur_perm, *new_perm, *tail_perm = NULL; tail = *dst; while (tail && tail->next) { tail = tail->next; } cur = list; while (cur) { if ((new_rule = (avrule_t *) malloc(sizeof(avrule_t))) == NULL) { goto cleanup; } avrule_init(new_rule); new_rule->specified = cur->specified; new_rule->flags = cur->flags; if (type_set_convert (&cur->stypes, &new_rule->stypes, module, state) == -1 || type_set_convert(&cur->ttypes, &new_rule->ttypes, module, state) == -1) { goto cleanup; } cur_perm = cur->perms; tail_perm = NULL; while (cur_perm) { if ((new_perm = (class_perm_node_t *) malloc(sizeof(class_perm_node_t))) == NULL) { goto cleanup; } class_perm_node_init(new_perm); new_perm->tclass = module->map[SYM_CLASSES][cur_perm->tclass - 1]; assert(new_perm->tclass); if (new_rule->specified & AVRULE_AV) { for (i = 0; i < module->perm_map_len[cur_perm->tclass - 1]; i++) { if (!(cur_perm->data & (1U << i))) continue; new_perm->data |= (1U << (module-> perm_map[cur_perm->tclass - 1][i] - 1)); } } else { new_perm->data = module->map[SYM_TYPES][cur_perm->data - 1]; } if (new_rule->perms == NULL) { new_rule->perms = new_perm; } else { assert(tail_perm); tail_perm->next = new_perm; } tail_perm = new_perm; cur_perm = cur_perm->next; } if (cur->xperms) { new_rule->xperms = calloc(1, sizeof(*new_rule->xperms)); if (!new_rule->xperms) goto cleanup; memcpy(new_rule->xperms, cur->xperms, sizeof(*new_rule->xperms)); } new_rule->line = cur->line; new_rule->source_line = cur->source_line; if (cur->source_filename) { new_rule->source_filename = strdup(cur->source_filename); if (!new_rule->source_filename) goto cleanup; } cur = cur->next; if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; } return 0; cleanup: ERR(state->handle, "Out of memory!"); avrule_destroy(new_rule); free(new_rule); return -1; } static int copy_role_trans_list(role_trans_rule_t * list, role_trans_rule_t ** dst, policy_module_t * module, link_state_t * state) { role_trans_rule_t *cur, *new_rule = NULL, *tail; unsigned int i; ebitmap_node_t *cnode; cur = list; tail = *dst; while (tail && tail->next) { tail = tail->next; } while (cur) { if ((new_rule = (role_trans_rule_t *) malloc(sizeof(role_trans_rule_t))) == NULL) { goto cleanup; } role_trans_rule_init(new_rule); if (role_set_or_convert (&cur->roles, &new_rule->roles, module, state) || type_set_or_convert(&cur->types, &new_rule->types, module, state)) { goto cleanup; } ebitmap_for_each_bit(&cur->classes, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { assert(module->map[SYM_CLASSES][i]); if (ebitmap_set_bit(&new_rule->classes, module-> map[SYM_CLASSES][i] - 1, 1)) { goto cleanup; } } } new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1]; if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); role_trans_rule_list_destroy(new_rule); return -1; } static int copy_role_allow_list(role_allow_rule_t * list, role_allow_rule_t ** dst, policy_module_t * module, link_state_t * state) { role_allow_rule_t *cur, *new_rule = NULL, *tail; cur = list; tail = *dst; while (tail && tail->next) { tail = tail->next; } while (cur) { if ((new_rule = (role_allow_rule_t *) malloc(sizeof(role_allow_rule_t))) == NULL) { goto cleanup; } role_allow_rule_init(new_rule); if (role_set_or_convert (&cur->roles, &new_rule->roles, module, state) || role_set_or_convert(&cur->new_roles, &new_rule->new_roles, module, state)) { goto cleanup; } if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); role_allow_rule_list_destroy(new_rule); return -1; } static int copy_filename_trans_list(filename_trans_rule_t * list, filename_trans_rule_t ** dst, policy_module_t * module, link_state_t * state) { filename_trans_rule_t *cur, *new_rule, *tail; cur = list; tail = *dst; while (tail && tail->next) tail = tail->next; while (cur) { new_rule = malloc(sizeof(*new_rule)); if (!new_rule) goto err; filename_trans_rule_init(new_rule); if (*dst == NULL) *dst = new_rule; else tail->next = new_rule; tail = new_rule; new_rule->name = strdup(cur->name); if (!new_rule->name) goto err; if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module, state) || type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module, state)) goto err; new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1]; new_rule->otype = module->map[SYM_TYPES][cur->otype - 1]; cur = cur->next; } return 0; err: ERR(state->handle, "Out of memory!"); return -1; } static int copy_range_trans_list(range_trans_rule_t * rules, range_trans_rule_t ** dst, policy_module_t * mod, link_state_t * state) { range_trans_rule_t *rule, *new_rule = NULL; unsigned int i; ebitmap_node_t *cnode; for (rule = rules; rule; rule = rule->next) { new_rule = (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t)); if (!new_rule) goto cleanup; range_trans_rule_init(new_rule); new_rule->next = *dst; *dst = new_rule; if (type_set_convert(&rule->stypes, &new_rule->stypes, mod, state)) goto cleanup; if (type_set_convert(&rule->ttypes, &new_rule->ttypes, mod, state)) goto cleanup; ebitmap_for_each_bit(&rule->tclasses, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { assert(mod->map[SYM_CLASSES][i]); if (ebitmap_set_bit (&new_rule->tclasses, mod->map[SYM_CLASSES][i] - 1, 1)) { goto cleanup; } } } if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state)) goto cleanup; } return 0; cleanup: ERR(state->handle, "Out of memory!"); range_trans_rule_list_destroy(new_rule); return -1; } static int copy_cond_list(cond_node_t * list, cond_node_t ** dst, policy_module_t * module, link_state_t * state) { unsigned i; cond_node_t *cur, *new_node = NULL, *tail; cond_expr_t *cur_expr; tail = *dst; while (tail && tail->next) tail = tail->next; cur = list; while (cur) { new_node = (cond_node_t *) malloc(sizeof(cond_node_t)); if (!new_node) { goto cleanup; } memset(new_node, 0, sizeof(cond_node_t)); new_node->cur_state = cur->cur_state; new_node->expr = cond_copy_expr(cur->expr); if (!new_node->expr) goto cleanup; /* go back through and remap the expression */ for (cur_expr = new_node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { /* expression nodes don't have a bool value of 0 - don't map them */ if (cur_expr->expr_type != COND_BOOL) continue; assert(module->map[SYM_BOOLS][cur_expr->bool - 1] != 0); cur_expr->bool = module->map[SYM_BOOLS][cur_expr->bool - 1]; } new_node->nbools = cur->nbools; /* FIXME should COND_MAX_BOOLS be used here? */ for (i = 0; i < min(cur->nbools, COND_MAX_BOOLS); i++) { uint32_t remapped_id = module->map[SYM_BOOLS][cur->bool_ids[i] - 1]; assert(remapped_id != 0); new_node->bool_ids[i] = remapped_id; } new_node->expr_pre_comp = cur->expr_pre_comp; if (copy_avrule_list (cur->avtrue_list, &new_node->avtrue_list, module, state) || copy_avrule_list(cur->avfalse_list, &new_node->avfalse_list, module, state)) { goto cleanup; } if (*dst == NULL) { *dst = new_node; } else { tail->next = new_node; } tail = new_node; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); cond_node_destroy(new_node); free(new_node); return -1; } /*********** functions that copy avrule_decls from module to base ***********/ static int copy_identifiers(link_state_t * state, symtab_t * src_symtab, avrule_decl_t * dest_decl) { int i, ret; state->dest_decl = dest_decl; for (i = 0; i < SYM_NUM; i++) { if (copy_callback_f[i] != NULL) { ret = hashtab_map(src_symtab[i].table, copy_callback_f[i], state); if (ret) { return ret; } } } if (hashtab_map(src_symtab[SYM_TYPES].table, type_bounds_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_TYPES].table, alias_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_ROLES].table, role_bounds_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_USERS].table, user_bounds_copy_callback, state)) return -1; /* then fix bitmaps associated with those newly copied identifiers */ for (i = 0; i < SYM_NUM; i++) { if (fix_callback_f[i] != NULL && hashtab_map(src_symtab[i].table, fix_callback_f[i], state)) { return -1; } } return 0; } static int copy_scope_index(scope_index_t * src, scope_index_t * dest, policy_module_t * module, link_state_t * state) { unsigned int i, j; uint32_t largest_mapped_class_value = 0; ebitmap_node_t *node; /* copy the scoping information for this avrule decl block */ for (i = 0; i < SYM_NUM; i++) { ebitmap_t *srcmap = src->scope + i; ebitmap_t *destmap = dest->scope + i; if (copy_callback_f[i] == NULL) { continue; } ebitmap_for_each_bit(srcmap, node, j) { if (ebitmap_node_get_bit(node, j)) { assert(module->map[i][j] != 0); if (ebitmap_set_bit (destmap, module->map[i][j] - 1, 1) != 0) { goto cleanup; } if (i == SYM_CLASSES && largest_mapped_class_value < module->map[SYM_CLASSES][j]) { largest_mapped_class_value = module->map[SYM_CLASSES][j]; } } } } /* next copy the enabled permissions data */ if ((dest->class_perms_map = malloc(largest_mapped_class_value * sizeof(*dest->class_perms_map))) == NULL) { goto cleanup; } for (i = 0; i < largest_mapped_class_value; i++) { ebitmap_init(dest->class_perms_map + i); } dest->class_perms_len = largest_mapped_class_value; for (i = 0; i < src->class_perms_len; i++) { ebitmap_t *srcmap = src->class_perms_map + i; ebitmap_t *destmap = dest->class_perms_map + module->map[SYM_CLASSES][i] - 1; ebitmap_for_each_bit(srcmap, node, j) { if (ebitmap_node_get_bit(node, j) && ebitmap_set_bit(destmap, module->perm_map[i][j] - 1, 1)) { goto cleanup; } } } return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } static int copy_avrule_decl(link_state_t * state, policy_module_t * module, avrule_decl_t * src_decl, avrule_decl_t * dest_decl) { int ret; /* copy all of the RBAC and TE rules */ if (copy_avrule_list (src_decl->avrules, &dest_decl->avrules, module, state) == -1 || copy_role_trans_list(src_decl->role_tr_rules, &dest_decl->role_tr_rules, module, state) == -1 || copy_role_allow_list(src_decl->role_allow_rules, &dest_decl->role_allow_rules, module, state) == -1 || copy_cond_list(src_decl->cond_list, &dest_decl->cond_list, module, state) == -1) { return -1; } if (copy_filename_trans_list(src_decl->filename_trans_rules, &dest_decl->filename_trans_rules, module, state)) return -1; if (copy_range_trans_list(src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state)) return -1; /* finally copy any identifiers local to this declaration */ ret = copy_identifiers(state, src_decl->symtab, dest_decl); if (ret < 0) { return ret; } /* then copy required and declared scope indices here */ if (copy_scope_index(&src_decl->required, &dest_decl->required, module, state) == -1 || copy_scope_index(&src_decl->declared, &dest_decl->declared, module, state) == -1) { return -1; } return 0; } static int copy_avrule_block(link_state_t * state, policy_module_t * module, avrule_block_t * block) { avrule_block_t *new_block = avrule_block_create(); avrule_decl_t *decl, *last_decl = NULL; int ret; if (new_block == NULL) { ERR(state->handle, "Out of memory!"); ret = -1; goto cleanup; } new_block->flags = block->flags; for (decl = block->branch_list; decl != NULL; decl = decl->next) { avrule_decl_t *new_decl = avrule_decl_create(state->next_decl_id); if (new_decl == NULL) { ERR(state->handle, "Out of memory!"); ret = -1; goto cleanup; } if (module->policy->name != NULL) { new_decl->module_name = strdup(module->policy->name); if (new_decl->module_name == NULL) { ERR(state->handle, "Out of memory\n"); avrule_decl_destroy(new_decl); ret = -1; goto cleanup; } } if (last_decl == NULL) { new_block->branch_list = new_decl; } else { last_decl->next = new_decl; } last_decl = new_decl; state->base->decl_val_to_struct[state->next_decl_id - 1] = new_decl; state->decl_to_mod[state->next_decl_id] = module->policy; module->avdecl_map[decl->decl_id] = new_decl->decl_id; ret = copy_avrule_decl(state, module, decl, new_decl); if (ret) { avrule_decl_destroy(new_decl); goto cleanup; } state->next_decl_id++; } state->last_avrule_block->next = new_block; state->last_avrule_block = new_block; return 0; cleanup: avrule_block_list_destroy(new_block); return ret; } static int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { unsigned int i; int ret; char *id = key, *new_id = NULL; scope_datum_t *scope, *base_scope; link_state_t *state = (link_state_t *) data; uint32_t symbol_num = state->symbol_num; uint32_t *avdecl_map = state->cur->avdecl_map; scope = (scope_datum_t *) datum; /* check if the base already has a scope entry */ base_scope = hashtab_search(state->base->scope[symbol_num].table, id); if (base_scope == NULL) { scope_datum_t *new_scope; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_scope = (scope_datum_t *) calloc(1, sizeof(*new_scope))) == NULL) { free(new_id); goto cleanup; } ret = hashtab_insert(state->base->scope[symbol_num].table, (hashtab_key_t) new_id, (hashtab_datum_t) new_scope); if (ret) { free(new_id); free(new_scope); goto cleanup; } new_scope->scope = SCOPE_REQ; /* this is reset further down */ base_scope = new_scope; } if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_DECL) { /* this module declared symbol, so overwrite the old * list with the new decl ids */ base_scope->scope = SCOPE_DECL; free(base_scope->decl_ids); base_scope->decl_ids = NULL; base_scope->decl_ids_len = 0; for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } else if (base_scope->scope == SCOPE_DECL && scope->scope == SCOPE_REQ) { /* this module depended on a symbol that now exists, * so don't do anything */ } else if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_REQ) { /* symbol is still required, so add to the list */ for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } else { /* this module declared a symbol, and it was already * declared. only roles and users may be multiply * declared; for all others this is an error. */ if (symbol_num != SYM_ROLES && symbol_num != SYM_USERS) { ERR(state->handle, "%s: Duplicate declaration in module: %s %s", state->cur_mod_name, symtab_names[state->symbol_num], id); return -1; } for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } /* Copy a module over to a base, remapping all values within. After * all identifiers and rules are done, copy the scoping information. * This is when it checks for duplicate declarations. */ static int copy_module(link_state_t * state, policy_module_t * module) { int i, ret; avrule_block_t *cur; state->cur = module; state->cur_mod_name = module->policy->name; /* first copy all of the identifiers */ ret = copy_identifiers(state, module->policy->symtab, NULL); if (ret) { return ret; } /* next copy all of the avrule blocks */ for (cur = module->policy->global; cur != NULL; cur = cur->next) { ret = copy_avrule_block(state, module, cur); if (ret) { return ret; } } /* then copy the scoping tables */ for (i = 0; i < SYM_NUM; i++) { state->symbol_num = i; if (hashtab_map (module->policy->scope[i].table, scope_copy_callback, state)) { return -1; } } return 0; } /***** functions that check requirements and enable blocks in a module ******/ /* borrowed from checkpolicy.c */ struct find_perm_arg { unsigned int valuep; hashtab_key_t key; }; static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg) { struct find_perm_arg *arg = varg; perm_datum_t *perdatum = (perm_datum_t *) datum; if (arg->valuep == perdatum->s.value) { arg->key = key; return 1; } return 0; } /* Check if the requirements are met for a single declaration. If all * are met return 1. For the first requirement found to be missing, * if 'missing_sym_num' and 'missing_value' are both not NULL then * write to them the symbol number and value for the missing * declaration. Then return 0 to indicate a missing declaration. * Note that if a declaration had no requirement at all (e.g., an ELSE * block) this returns 1. */ static int is_decl_requires_met(link_state_t * state, avrule_decl_t * decl, struct missing_requirement *req) { /* (This algorithm is very unoptimized. It performs many * redundant checks. A very obvious improvement is to cache * which symbols have been verified, so that they do not need * to be re-checked.) */ unsigned int i, j; ebitmap_t *bitmap; char *id, *perm_id; policydb_t *pol = state->base; ebitmap_node_t *node; /* check that all symbols have been satisfied */ for (i = 0; i < SYM_NUM; i++) { if (i == SYM_CLASSES) { /* classes will be checked during permissions * checking phase below */ continue; } bitmap = &decl->required.scope[i]; ebitmap_for_each_bit(bitmap, node, j) { if (!ebitmap_node_get_bit(node, j)) { continue; } /* check base's scope table */ id = pol->sym_val_to_name[i][j]; if (!is_id_enabled(id, state->base, i)) { /* this symbol was not found */ if (req != NULL) { req->symbol_type = i; req->symbol_value = j + 1; } return 0; } } } /* check that all classes and permissions have been satisfied */ for (i = 0; i < decl->required.class_perms_len; i++) { bitmap = decl->required.class_perms_map + i; ebitmap_for_each_bit(bitmap, node, j) { struct find_perm_arg fparg; class_datum_t *cladatum; uint32_t perm_value = j + 1; int rc; scope_datum_t *scope; if (!ebitmap_node_get_bit(node, j)) { continue; } id = pol->p_class_val_to_name[i]; cladatum = pol->class_val_to_struct[i]; scope = hashtab_search(state->base->p_classes_scope.table, id); if (scope == NULL) { ERR(state->handle, "Could not find scope information for class %s", id); return -1; } fparg.valuep = perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); if (fparg.key == NULL && cladatum->comdatum != NULL) { rc = hashtab_map(cladatum->comdatum->permissions.table, find_perm, &fparg); assert(rc == 1); } perm_id = fparg.key; assert(perm_id != NULL); if (!is_perm_enabled(id, perm_id, state->base)) { if (req != NULL) { req->symbol_type = SYM_CLASSES; req->symbol_value = i + 1; req->perm_value = perm_value; } return 0; } } } /* all requirements have been met */ return 1; } static int debug_requirements(link_state_t * state, policydb_t * p) { int ret; avrule_block_t *cur; missing_requirement_t req; memset(&req, 0, sizeof(req)); for (cur = p->global; cur != NULL; cur = cur->next) { if (cur->enabled != NULL) continue; ret = is_decl_requires_met(state, cur->branch_list, &req); if (ret < 0) { return ret; } else if (ret == 0) { const char *mod_name = cur->branch_list->module_name ? cur->branch_list->module_name : "BASE"; if (req.symbol_type == SYM_CLASSES) { struct find_perm_arg fparg; class_datum_t *cladatum; cladatum = p->class_val_to_struct[req.symbol_value - 1]; fparg.valuep = req.perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); if (cur->flags & AVRULE_OPTIONAL) { ERR(state->handle, "%s[%d]'s optional requirements were not met: class %s, permission %s", mod_name, cur->branch_list->decl_id, p->p_class_val_to_name[req.symbol_value - 1], fparg.key); } else { ERR(state->handle, "%s[%d]'s global requirements were not met: class %s, permission %s", mod_name, cur->branch_list->decl_id, p->p_class_val_to_name[req.symbol_value - 1], fparg.key); } } else { if (cur->flags & AVRULE_OPTIONAL) { ERR(state->handle, "%s[%d]'s optional requirements were not met: %s %s", mod_name, cur->branch_list->decl_id, symtab_names[req.symbol_type], p->sym_val_to_name[req. symbol_type][req. symbol_value - 1]); } else { ERR(state->handle, "%s[%d]'s global requirements were not met: %s %s", mod_name, cur->branch_list->decl_id, symtab_names[req.symbol_type], p->sym_val_to_name[req. symbol_type][req. symbol_value - 1]); } } } } return 0; } static void print_missing_requirements(link_state_t * state, avrule_block_t * cur, missing_requirement_t * req) { policydb_t *p = state->base; const char *mod_name = cur->branch_list->module_name ? cur->branch_list->module_name : "BASE"; if (req->symbol_type == SYM_CLASSES) { struct find_perm_arg fparg; class_datum_t *cladatum; cladatum = p->class_val_to_struct[req->symbol_value - 1]; fparg.valuep = req->perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); ERR(state->handle, "%s's global requirements were not met: class %s, permission %s", mod_name, p->p_class_val_to_name[req->symbol_value - 1], fparg.key); } else { ERR(state->handle, "%s's global requirements were not met: %s %s", mod_name, symtab_names[req->symbol_type], p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]); } } /* Enable all of the avrule_decl blocks for the policy. This simple * algorithm is the following: * * 1) Enable all of the non-else avrule_decls for all blocks. * 2) Iterate through the non-else decls looking for decls whose requirements * are not met. * 2a) If the decl is non-optional, return immediately with an error. * 2b) If the decl is optional, disable the block and mark changed = 1 * 3) If changed == 1 goto 2. * 4) Iterate through all blocks looking for those that have no enabled * decl. If the block has an else decl, enable. * * This will correctly handle all dependencies, including mutual and * cicular. The only downside is that it is slow. */ static int enable_avrules(link_state_t * state, policydb_t * pol) { int changed = 1; avrule_block_t *block; avrule_decl_t *decl; missing_requirement_t req; int ret = 0, rc; if (state->verbose) { INFO(state->handle, "Determining which avrules to enable."); } /* 1) enable all of the non-else blocks */ for (block = pol->global; block != NULL; block = block->next) { block->enabled = block->branch_list; block->enabled->enabled = 1; for (decl = block->branch_list->next; decl != NULL; decl = decl->next) decl->enabled = 0; } /* 2) Iterate */ while (changed) { changed = 0; for (block = pol->global; block != NULL; block = block->next) { if (block->enabled == NULL) { continue; } decl = block->branch_list; if (state->verbose) { const char *mod_name = decl->module_name ? decl->module_name : "BASE"; INFO(state->handle, "check module %s decl %d\n", mod_name, decl->decl_id); } rc = is_decl_requires_met(state, decl, &req); if (rc < 0) { ret = SEPOL_ERR; goto out; } else if (rc == 0) { decl->enabled = 0; block->enabled = NULL; changed = 1; if (!(block->flags & AVRULE_OPTIONAL)) { print_missing_requirements(state, block, &req); ret = SEPOL_EREQ; goto out; } } } } /* 4) else handling * * Iterate through all of the blocks skipping the first (which is the * global block, is required to be present, and cannot have an else). * If the block is disabled and has an else decl, enable that. * * This code assumes that the second block in the branch list is the else * block. This is currently supported by the compiler. */ for (block = pol->global->next; block != NULL; block = block->next) { if (block->enabled == NULL) { if (block->branch_list->next != NULL) { block->enabled = block->branch_list->next; block->branch_list->next->enabled = 1; } } } out: if (state->verbose) debug_requirements(state, pol); return ret; } /*********** the main linking functions ***********/ /* Given a module's policy, normalize all conditional expressions * within. Return 0 on success, -1 on error. */ static int cond_normalize(policydb_t * p) { avrule_block_t *block; for (block = p->global; block != NULL; block = block->next) { avrule_decl_t *decl; for (decl = block->branch_list; decl != NULL; decl = decl->next) { cond_list_t *cond = decl->cond_list; while (cond) { if (cond_normalize_expr(p, cond) < 0) return -1; cond = cond->next; } } } return 0; } /* Allocate space for the various remapping arrays. */ static int prepare_module(link_state_t * state, policy_module_t * module) { int i; uint32_t items, num_decls = 0; avrule_block_t *cur; /* allocate the maps */ for (i = 0; i < SYM_NUM; i++) { items = module->policy->symtab[i].nprim; if ((module->map[i] = (uint32_t *) calloc(items, sizeof(*module->map[i]))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } } /* allocate the permissions remap here */ items = module->policy->p_classes.nprim; if ((module->perm_map_len = calloc(items, sizeof(*module->perm_map_len))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } if ((module->perm_map = calloc(items, sizeof(*module->perm_map))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } /* allocate a map for avrule_decls */ for (cur = module->policy->global; cur != NULL; cur = cur->next) { avrule_decl_t *decl; for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (decl->decl_id > num_decls) { num_decls = decl->decl_id; } } } num_decls++; if ((module->avdecl_map = calloc(num_decls, sizeof(uint32_t))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } module->num_decls = num_decls; /* normalize conditionals within */ if (cond_normalize(module->policy) < 0) { ERR(state->handle, "Error while normalizing conditionals within the module %s.", module->policy->name); return -1; } return 0; } static int prepare_base(link_state_t * state, uint32_t num_mod_decls) { avrule_block_t *cur = state->base->global; assert(cur != NULL); state->next_decl_id = 0; /* iterate through all of the declarations in the base, to determine what the next decl_id should be */ while (cur != NULL) { avrule_decl_t *decl; for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (decl->decl_id > state->next_decl_id) { state->next_decl_id = decl->decl_id; } } state->last_avrule_block = cur; cur = cur->next; } state->last_base_avrule_block = state->last_avrule_block; state->next_decl_id++; /* allocate the table mapping from base's decl_id to its * avrule_decls and set the initial mappings */ free(state->base->decl_val_to_struct); if ((state->base->decl_val_to_struct = calloc(state->next_decl_id + num_mod_decls, sizeof(*(state->base->decl_val_to_struct)))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } /* This allocates the decl block to module mapping used for error reporting */ if ((state->decl_to_mod = calloc(state->next_decl_id + num_mod_decls, sizeof(*(state->decl_to_mod)))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } cur = state->base->global; while (cur != NULL) { avrule_decl_t *decl = cur->branch_list; while (decl != NULL) { state->base->decl_val_to_struct[decl->decl_id - 1] = decl; state->decl_to_mod[decl->decl_id] = state->base; decl = decl->next; } cur = cur->next; } /* normalize conditionals within */ if (cond_normalize(state->base) < 0) { ERR(state->handle, "Error while normalizing conditionals within the base module."); return -1; } return 0; } static int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum, void * data) { char *id; role_datum_t *role, *sub_attr; link_state_t *state; unsigned int i; ebitmap_node_t *rnode; id = key; role = (role_datum_t *)datum; state = (link_state_t *)data; if (strcmp(id, OBJECT_R) == 0){ /* object_r is never a role attribute by far */ return 0; } if (role->flavor != ROLE_ATTRIB) return 0; if (state->verbose) INFO(state->handle, "expanding role attribute %s", id); restart: ebitmap_for_each_bit(&role->roles, rnode, i) { if (ebitmap_node_get_bit(rnode, i)) { sub_attr = state->base->role_val_to_struct[i]; if (sub_attr->flavor != ROLE_ATTRIB) continue; /* remove the sub role attribute from the parent * role attribute's roles ebitmap */ if (ebitmap_set_bit(&role->roles, i, 0)) return -1; /* loop dependency of role attributes */ if (sub_attr->s.value == role->s.value) continue; /* now go on to expand a sub role attribute * by escalating its roles ebitmap */ if (ebitmap_union(&role->roles, &sub_attr->roles)) { ERR(state->handle, "Out of memory!"); return -1; } /* sub_attr->roles may contain other role attributes, * re-scan the parent role attribute's roles ebitmap */ goto restart; } } return 0; } /* For any role attribute in a declaration's local symtab[SYM_ROLES] table, * copy its roles ebitmap into its duplicate's in the base->p_roles.table. */ static int populate_decl_roleattributes(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; role_datum_t *decl_role, *base_role; link_state_t *state = (link_state_t *)data; decl_role = (role_datum_t *)datum; if (strcmp(id, OBJECT_R) == 0) { /* object_r is never a role attribute by far */ return 0; } if (decl_role->flavor != ROLE_ATTRIB) return 0; base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table, id); assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB); if (ebitmap_union(&base_role->roles, &decl_role->roles)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int populate_roleattributes(link_state_t *state, policydb_t *pol) { avrule_block_t *block; avrule_decl_t *decl; if (state->verbose) INFO(state->handle, "Populating role-attribute relationship " "from enabled declarations' local symtab."); /* Iterate through all of the blocks skipping the first(which is the * global block, is required to be present and can't have an else). * If the block is disabled or not having an enabled decl, skip it. */ for (block = pol->global->next; block != NULL; block = block->next) { decl = block->enabled; if (decl == NULL || decl->enabled == 0) continue; if (hashtab_map(decl->symtab[SYM_ROLES].table, populate_decl_roleattributes, state)) return -1; } return 0; } /* Link a set of modules into a base module. This process is somewhat * similar to an actual compiler: it requires a set of order dependent * steps. The base and every module must have been indexed prior to * calling this function. */ int link_modules(sepol_handle_t * handle, policydb_t * b, policydb_t ** mods, int len, int verbose) { int i, ret, retval = -1; policy_module_t **modules = NULL; link_state_t state; uint32_t num_mod_decls = 0; memset(&state, 0, sizeof(state)); state.base = b; state.verbose = verbose; state.handle = handle; if (b->policy_type != POLICY_BASE) { ERR(state.handle, "Target of link was not a base policy."); return -1; } /* first allocate some space to hold the maps from module * symbol's value to the destination symbol value; then do * other preparation work */ if ((modules = (policy_module_t **) calloc(len, sizeof(*modules))) == NULL) { ERR(state.handle, "Out of memory!"); return -1; } for (i = 0; i < len; i++) { if (mods[i]->policy_type != POLICY_MOD) { ERR(state.handle, "Tried to link in a policy that was not a module."); goto cleanup; } if (mods[i]->mls != b->mls) { if (b->mls) ERR(state.handle, "Tried to link in a non-MLS module with an MLS base."); else ERR(state.handle, "Tried to link in an MLS module with a non-MLS base."); goto cleanup; } if (mods[i]->policyvers > b->policyvers) { WARN(state.handle, "Upgrading policy version from %u to %u\n", b->policyvers, mods[i]->policyvers); b->policyvers = mods[i]->policyvers; } if ((modules[i] = (policy_module_t *) calloc(1, sizeof(policy_module_t))) == NULL) { ERR(state.handle, "Out of memory!"); goto cleanup; } modules[i]->policy = mods[i]; if (prepare_module(&state, modules[i]) == -1) { goto cleanup; } num_mod_decls += modules[i]->num_decls; } if (prepare_base(&state, num_mod_decls) == -1) { goto cleanup; } /* copy all types, declared and required */ for (i = 0; i < len; i++) { state.cur = modules[i]; state.cur_mod_name = modules[i]->policy->name; ret = hashtab_map(modules[i]->policy->p_types.table, type_copy_callback, &state); if (ret) { retval = ret; goto cleanup; } } /* then copy everything else, including aliases, and fixup attributes */ for (i = 0; i < len; i++) { state.cur = modules[i]; state.cur_mod_name = modules[i]->policy->name; ret = copy_identifiers(&state, modules[i]->policy->symtab, NULL); if (ret) { retval = ret; goto cleanup; } } if (policydb_index_others(state.handle, state.base, 0)) { ERR(state.handle, "Error while indexing others"); goto cleanup; } /* copy and remap the module's data over to base */ for (i = 0; i < len; i++) { state.cur = modules[i]; ret = copy_module(&state, modules[i]); if (ret) { retval = ret; goto cleanup; } } /* re-index base, for symbols were added to symbol tables */ if (policydb_index_classes(state.base)) { ERR(state.handle, "Error while indexing classes"); goto cleanup; } if (policydb_index_others(state.handle, state.base, 0)) { ERR(state.handle, "Error while indexing others"); goto cleanup; } if (enable_avrules(&state, state.base)) { retval = SEPOL_EREQ; goto cleanup; } /* Now that all role attribute's roles ebitmap have been settled, * escalate sub role attribute's roles ebitmap into that of parent. * * First, since some role-attribute relationships could be recorded * in some decl's local symtab(see get_local_role()), we need to * populate them up to the base.p_roles table. */ if (populate_roleattributes(&state, state.base)) { retval = SEPOL_EREQ; goto cleanup; } /* Now do the escalation. */ if (hashtab_map(state.base->p_roles.table, expand_role_attributes, &state)) goto cleanup; retval = 0; cleanup: for (i = 0; modules != NULL && i < len; i++) { policy_module_destroy(modules[i]); } free(modules); free(state.decl_to_mod); return retval; } libsepol/src/mls.c0100644 0000000 0000000 00000044367 13756670065 013201 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the multi-level security (MLS) policy. */ #include #include #include #include #include #include "handle.h" #include "debug.h" #include "private.h" #include "mls.h" int mls_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * mls, char **str) { char *ptr = NULL, *ptr2 = NULL; /* Temporary buffer - length + NULL terminator */ int len = mls_compute_context_len(policydb, mls) + 1; ptr = (char *)malloc(len); if (ptr == NULL) goto omem; /* Final string w/ ':' cut off */ ptr2 = (char *)malloc(len - 1); if (ptr2 == NULL) goto omem; mls_sid_to_context(policydb, mls, &ptr); ptr -= len - 1; strcpy(ptr2, ptr + 1); free(ptr); *str = ptr2; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not convert mls context to string"); free(ptr); free(ptr2); return STATUS_ERR; } int mls_from_string(sepol_handle_t * handle, const policydb_t * policydb, const char *str, context_struct_t * mls) { char *tmp = strdup(str); char *tmp_cp = tmp; if (!tmp) goto omem; if (mls_context_to_sid(policydb, '$', &tmp_cp, mls) < 0) { ERR(handle, "invalid MLS context %s", str); free(tmp); goto err; } free(tmp); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not construct mls context structure"); return STATUS_ERR; } /* * Return the length in bytes for the MLS fields of the * security context string representation of `context'. */ int mls_compute_context_len(const policydb_t * policydb, const context_struct_t * context) { unsigned int i, l, len, range; ebitmap_node_t *cnode; if (!policydb->mls) return 0; len = 1; /* for the beginning ":" */ for (l = 0; l < 2; l++) { range = 0; len += strlen(policydb-> p_sens_val_to_name[context->range.level[l].sens - 1]); ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (range) { range++; continue; } len += strlen(policydb->p_cat_val_to_name[i]) + 1; range++; } else { if (range > 1) len += strlen(policydb-> p_cat_val_to_name[i - 1]) + 1; range = 0; } } /* Handle case where last category is the end of range */ if (range > 1) len += strlen(policydb->p_cat_val_to_name[i - 1]) + 1; if (l == 0) { if (mls_level_eq(&context->range.level[0], &context->range.level[1])) break; else len++; } } return len; } /* * Write the security context string representation of * the MLS fields of `context' into the string `*scontext'. * Update `*scontext' to point to the end of the MLS fields. */ void mls_sid_to_context(const policydb_t * policydb, const context_struct_t * context, char **scontext) { char *scontextp; unsigned int i, l, range, wrote_sep; ebitmap_node_t *cnode; if (!policydb->mls) return; scontextp = *scontext; *scontextp = ':'; scontextp++; for (l = 0; l < 2; l++) { range = 0; wrote_sep = 0; strcpy(scontextp, policydb->p_sens_val_to_name[context->range.level[l]. sens - 1]); scontextp += strlen(policydb-> p_sens_val_to_name[context->range.level[l].sens - 1]); /* categories */ ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (range) { range++; continue; } if (!wrote_sep) { *scontextp++ = ':'; wrote_sep = 1; } else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i]); scontextp += strlen(policydb->p_cat_val_to_name[i]); range++; } else { if (range > 1) { if (range > 2) *scontextp++ = '.'; else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]); scontextp += strlen(policydb-> p_cat_val_to_name[i - 1]); } range = 0; } } /* Handle case where last category is the end of range */ if (range > 1) { if (range > 2) *scontextp++ = '.'; else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]); scontextp += strlen(policydb->p_cat_val_to_name[i - 1]); } if (l == 0) { if (mls_level_eq(&context->range.level[0], &context->range.level[1])) break; else { *scontextp = '-'; scontextp++; } } } *scontext = scontextp; return; } /* * Return 1 if the MLS fields in the security context * structure `c' are valid. Return 0 otherwise. */ int mls_context_isvalid(const policydb_t * p, const context_struct_t * c) { level_datum_t *levdatum; user_datum_t *usrdatum; unsigned int i, l; ebitmap_node_t *cnode; hashtab_key_t key; if (!p->mls) return 1; /* * MLS range validity checks: high must dominate low, low level must * be valid (category set <-> sensitivity check), and high level must * be valid (category set <-> sensitivity check) */ if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) /* High does not dominate low. */ return 0; for (l = 0; l < 2; l++) { if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim) return 0; key = p->p_sens_val_to_name[c->range.level[l].sens - 1]; if (!key) return 0; levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, key); if (!levdatum) return 0; ebitmap_for_each_bit(&c->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (i > p->p_cats.nprim) return 0; if (!ebitmap_get_bit(&levdatum->level->cat, i)) /* * Category may not be associated with * sensitivity in low level. */ return 0; } } } if (c->role == OBJECT_R_VAL) return 1; /* * User must be authorized for the MLS range. */ if (!c->user || c->user > p->p_users.nprim) return 0; usrdatum = p->user_val_to_struct[c->user - 1]; if (!usrdatum || !mls_range_contains(usrdatum->exp_range, c->range)) return 0; /* user may not be associated with range */ return 1; } /* * Set the MLS fields in the security context structure * `context' based on the string representation in * the string `*scontext'. Update `*scontext' to * point to the end of the string representation of * the MLS fields. * * This function modifies the string in place, inserting * NULL characters to terminate the MLS fields. */ int mls_context_to_sid(const policydb_t * policydb, char oldc, char **scontext, context_struct_t * context) { char delim; char *scontextp, *p, *rngptr; level_datum_t *levdatum; cat_datum_t *catdatum, *rngdatum; unsigned int l; if (!policydb->mls) return 0; /* No MLS component to the security context */ if (!oldc) goto err; /* Extract low sensitivity. */ scontextp = p = *scontext; while (*p && *p != ':' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(policydb->p_levels.table, (hashtab_key_t) scontextp); if (!levdatum) goto err; context->range.level[l].sens = levdatum->level->sens; if (delim == ':') { /* Extract category set. */ while (1) { scontextp = p; while (*p && *p != ',' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; /* Separate into range if exists */ if ((rngptr = strchr(scontextp, '.')) != NULL) { /* Remove '.' */ *rngptr++ = 0; } catdatum = (cat_datum_t *) hashtab_search(policydb-> p_cats.table, (hashtab_key_t) scontextp); if (!catdatum) goto err; if (ebitmap_set_bit (&context->range.level[l].cat, catdatum->s.value - 1, 1)) goto err; /* If range, set all categories in range */ if (rngptr) { unsigned int i; rngdatum = (cat_datum_t *) hashtab_search(policydb->p_cats. table, (hashtab_key_t) rngptr); if (!rngdatum) goto err; if (catdatum->s.value >= rngdatum->s.value) goto err; for (i = catdatum->s.value; i < rngdatum->s.value; i++) { if (ebitmap_set_bit (&context->range.level[l]. cat, i, 1)) goto err; } } if (delim != ',') break; } } if (delim == '-') { /* Extract high sensitivity. */ scontextp = p; while (*p && *p != ':') p++; delim = *p; if (delim != 0) *p++ = 0; } else break; } /* High level is missing, copy low level */ if (l == 0) { if (mls_level_cpy(&context->range.level[1], &context->range.level[0]) < 0) goto err; } *scontext = ++p; return STATUS_SUCCESS; err: return STATUS_ERR; } /* * Copies the MLS range from `src' into `dst'. */ static inline int mls_copy_context(context_struct_t * dst, context_struct_t * src) { int l, rc = 0; /* Copy the MLS range from the source context */ for (l = 0; l < 2; l++) { dst->range.level[l].sens = src->range.level[l].sens; rc = ebitmap_cpy(&dst->range.level[l].cat, &src->range.level[l].cat); if (rc) break; } return rc; } /* * Copies the effective MLS range from `src' into `dst'. */ static inline int mls_scopy_context(context_struct_t * dst, context_struct_t * src) { int l, rc = 0; /* Copy the MLS range from the source context */ for (l = 0; l < 2; l++) { dst->range.level[l].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[l].cat, &src->range.level[0].cat); if (rc) break; } return rc; } /* * Copies the MLS range `range' into `context'. */ static inline int mls_range_set(context_struct_t * context, mls_range_t * range) { int l, rc = 0; /* Copy the MLS range into the context */ for (l = 0; l < 2; l++) { context->range.level[l].sens = range->level[l].sens; rc = ebitmap_cpy(&context->range.level[l].cat, &range->level[l].cat); if (rc) break; } return rc; } int mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user, context_struct_t * usercon, int mls) { if (mls) { mls_level_t *fromcon_sen = &(fromcon->range.level[0]); mls_level_t *fromcon_clr = &(fromcon->range.level[1]); mls_level_t *user_low = &(user->exp_range.level[0]); mls_level_t *user_clr = &(user->exp_range.level[1]); mls_level_t *user_def = &(user->exp_dfltlevel); mls_level_t *usercon_sen = &(usercon->range.level[0]); mls_level_t *usercon_clr = &(usercon->range.level[1]); /* Honor the user's default level if we can */ if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { *usercon_sen = *user_def; } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { *usercon_sen = *fromcon_sen; } else if (mls_level_between(fromcon_clr, user_low, user_def)) { *usercon_sen = *user_low; } else return -EINVAL; /* Lower the clearance of available contexts if the clearance of "fromcon" is lower than that of the user's default clearance (but only if the "fromcon" clearance dominates the user's computed sensitivity level) */ if (mls_level_dom(user_clr, fromcon_clr)) { *usercon_clr = *fromcon_clr; } else if (mls_level_dom(fromcon_clr, user_clr)) { *usercon_clr = *user_clr; } else return -EINVAL; } return 0; } /* * Convert the MLS fields in the security context * structure `c' from the values specified in the * policy `oldp' to the values specified in the policy `newp'. */ int mls_convert_context(policydb_t * oldp, policydb_t * newp, context_struct_t * c) { level_datum_t *levdatum; cat_datum_t *catdatum; ebitmap_t bitmap; unsigned int l, i; ebitmap_node_t *cnode; if (!oldp->mls) return 0; for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(newp->p_levels.table, oldp-> p_sens_val_to_name[c-> range. level [l]. sens - 1]); if (!levdatum) return -EINVAL; c->range.level[l].sens = levdatum->level->sens; ebitmap_init(&bitmap); ebitmap_for_each_bit(&c->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { int rc; catdatum = (cat_datum_t *) hashtab_search(newp->p_cats. table, oldp-> p_cat_val_to_name [i]); if (!catdatum) return -EINVAL; rc = ebitmap_set_bit(&bitmap, catdatum->s.value - 1, 1); if (rc) return rc; } } ebitmap_destroy(&c->range.level[l].cat); c->range.level[l].cat = bitmap; } return 0; } int mls_compute_sid(policydb_t * policydb, context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, uint32_t specified, context_struct_t * newcontext) { range_trans_t rtr; struct mls_range *r; struct class_datum *cladatum; int default_range = 0; if (!policydb->mls) return 0; switch (specified) { case AVTAB_TRANSITION: /* Look for a range transition rule. */ rtr.source_type = scontext->type; rtr.target_type = tcontext->type; rtr.target_class = tclass; r = hashtab_search(policydb->range_tr, (hashtab_key_t) &rtr); if (r) return mls_range_set(newcontext, r); if (tclass && tclass <= policydb->p_classes.nprim) { cladatum = policydb->class_val_to_struct[tclass - 1]; if (cladatum) default_range = cladatum->default_range; } switch (default_range) { case DEFAULT_SOURCE_LOW: return mls_context_cpy_low(newcontext, scontext); case DEFAULT_SOURCE_HIGH: return mls_context_cpy_high(newcontext, scontext); case DEFAULT_SOURCE_LOW_HIGH: return mls_context_cpy(newcontext, scontext); case DEFAULT_TARGET_LOW: return mls_context_cpy_low(newcontext, tcontext); case DEFAULT_TARGET_HIGH: return mls_context_cpy_high(newcontext, tcontext); case DEFAULT_TARGET_LOW_HIGH: return mls_context_cpy(newcontext, tcontext); } /* Fallthrough */ case AVTAB_CHANGE: if (tclass == SECCLASS_PROCESS) /* Use the process MLS attributes. */ return mls_copy_context(newcontext, scontext); else /* Use the process effective MLS attributes. */ return mls_scopy_context(newcontext, scontext); case AVTAB_MEMBER: /* Use the process effective MLS attributes. */ return mls_context_cpy_low(newcontext, scontext); default: return -EINVAL; } return -EINVAL; } int sepol_mls_contains(sepol_handle_t * handle, sepol_policydb_t * policydb, const char *mls1, const char *mls2, int *response) { context_struct_t *ctx1 = NULL, *ctx2 = NULL; ctx1 = malloc(sizeof(context_struct_t)); ctx2 = malloc(sizeof(context_struct_t)); if (ctx1 == NULL || ctx2 == NULL) goto omem; context_init(ctx1); context_init(ctx2); if (mls_from_string(handle, &policydb->p, mls1, ctx1) < 0) goto err; if (mls_from_string(handle, &policydb->p, mls2, ctx2) < 0) goto err; *response = mls_range_contains(ctx1->range, ctx2->range); context_destroy(ctx1); context_destroy(ctx2); free(ctx1); free(ctx2); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not check if mls context %s contains %s", mls1, mls2); context_destroy(ctx1); context_destroy(ctx2); free(ctx1); free(ctx2); return STATUS_ERR; } int sepol_mls_check(sepol_handle_t * handle, sepol_policydb_t * policydb, const char *mls) { int ret; context_struct_t *con = malloc(sizeof(context_struct_t)); if (!con) { ERR(handle, "out of memory, could not check if " "mls context %s is valid", mls); return STATUS_ERR; } context_init(con); ret = mls_from_string(handle, &policydb->p, mls, con); context_destroy(con); free(con); return ret; } void mls_semantic_cat_init(mls_semantic_cat_t * c) { memset(c, 0, sizeof(mls_semantic_cat_t)); } void mls_semantic_cat_destroy(mls_semantic_cat_t * c __attribute__ ((unused))) { /* it's currently a simple struct - really nothing to destroy */ return; } void mls_semantic_level_init(mls_semantic_level_t * l) { memset(l, 0, sizeof(mls_semantic_level_t)); } void mls_semantic_level_destroy(mls_semantic_level_t * l) { mls_semantic_cat_t *cur, *next; if (l == NULL) return; next = l->cat; while (next) { cur = next; next = cur->next; mls_semantic_cat_destroy(cur); free(cur); } } int mls_semantic_level_cpy(mls_semantic_level_t * dst, mls_semantic_level_t * src) { mls_semantic_cat_t *cat, *newcat, *lnewcat = NULL; mls_semantic_level_init(dst); dst->sens = src->sens; cat = src->cat; while (cat) { newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!newcat) goto err; mls_semantic_cat_init(newcat); if (lnewcat) lnewcat->next = newcat; else dst->cat = newcat; newcat->low = cat->low; newcat->high = cat->high; lnewcat = newcat; cat = cat->next; } return 0; err: mls_semantic_level_destroy(dst); return -1; } void mls_semantic_range_init(mls_semantic_range_t * r) { mls_semantic_level_init(&r->level[0]); mls_semantic_level_init(&r->level[1]); } void mls_semantic_range_destroy(mls_semantic_range_t * r) { mls_semantic_level_destroy(&r->level[0]); mls_semantic_level_destroy(&r->level[1]); } int mls_semantic_range_cpy(mls_semantic_range_t * dst, mls_semantic_range_t * src) { if (mls_semantic_level_cpy(&dst->level[0], &src->level[0]) < 0) return -1; if (mls_semantic_level_cpy(&dst->level[1], &src->level[1]) < 0) { mls_semantic_level_destroy(&dst->level[0]); return -1; } return 0; } libsepol/src/mls.h0100644 0000000 0000000 00000004517 13756670065 013177 0ustar000000000 0000000 /* Author: Stephen Smalley, * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_MLS_INTERNAL_H_ #define _SEPOL_MLS_INTERNAL_H_ #include "policydb_internal.h" #include #include "handle.h" extern int mls_from_string(sepol_handle_t * handle, const policydb_t * policydb, const char *str, context_struct_t * mls); extern int mls_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * mls, char **str); /* Deprecated */ extern int mls_compute_context_len(const policydb_t * policydb, const context_struct_t * context); /* Deprecated */ extern void mls_sid_to_context(const policydb_t * policydb, const context_struct_t * context, char **scontext); /* Deprecated */ extern int mls_context_to_sid(const policydb_t * policydb, char oldc, char **scontext, context_struct_t * context); extern int mls_context_isvalid(const policydb_t * p, const context_struct_t * c); extern int mls_convert_context(policydb_t * oldp, policydb_t * newp, context_struct_t * context); extern int mls_compute_sid(policydb_t * policydb, context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, uint32_t specified, context_struct_t * newcontext); extern int mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user, context_struct_t * usercon, int mls); #endif libsepol/src/module.c0100644 0000000 0000000 00000056525 13756670065 013672 0ustar000000000 0000000 /* Author: Karl MacMillan * Jason Tang * Chris PeBenito * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "policydb_internal.h" #include "module_internal.h" #include #include #include #include "debug.h" #include "private.h" #include #include #include #include #define SEPOL_PACKAGE_SECTION_FC 0xf97cff90 #define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91 #define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92 #define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93 static int policy_file_seek(struct policy_file *fp, size_t offset) { switch (fp->type) { case PF_USE_STDIO: if (offset > LONG_MAX) { errno = EFAULT; return -1; } return fseek(fp->fp, (long)offset, SEEK_SET); case PF_USE_MEMORY: if (offset > fp->size) { errno = EFAULT; return -1; } fp->data -= fp->size - fp->len; fp->data += offset; fp->len = fp->size - offset; return 0; default: return 0; } } static int policy_file_length(struct policy_file *fp, size_t *out) { long prev_offset, end_offset; int rc; switch (fp->type) { case PF_USE_STDIO: prev_offset = ftell(fp->fp); if (prev_offset < 0) return prev_offset; rc = fseek(fp->fp, 0L, SEEK_END); if (rc < 0) return rc; end_offset = ftell(fp->fp); if (end_offset < 0) return end_offset; rc = fseek(fp->fp, prev_offset, SEEK_SET); if (rc < 0) return rc; *out = end_offset; break; case PF_USE_MEMORY: *out = fp->size; break;; default: *out = 0; break; } return 0; } static int module_package_init(sepol_module_package_t * p) { memset(p, 0, sizeof(sepol_module_package_t)); if (sepol_policydb_create(&p->policy)) return -1; p->version = 1; return 0; } static int set_char(char **field, char *data, size_t len) { if (*field) { free(*field); *field = NULL; } if (len) { *field = malloc(len); if (!*field) return -1; memcpy(*field, data, len); } return 0; } int sepol_module_package_create(sepol_module_package_t ** p) { int rc; *p = calloc(1, sizeof(sepol_module_package_t)); if (!(*p)) return -1; rc = module_package_init(*p); if (rc < 0) free(*p); return rc; } hidden_def(sepol_module_package_create) /* Deallocates all memory associated with a module package, including * the pointer itself. Does nothing if p is NULL. */ void sepol_module_package_free(sepol_module_package_t * p) { if (p == NULL) return; sepol_policydb_free(p->policy); free(p->file_contexts); free(p->seusers); free(p->user_extra); free(p->netfilter_contexts); free(p); } hidden_def(sepol_module_package_free) char *sepol_module_package_get_file_contexts(sepol_module_package_t * p) { return p->file_contexts; } size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p) { return p->file_contexts_len; } char *sepol_module_package_get_seusers(sepol_module_package_t * p) { return p->seusers; } size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p) { return p->seusers_len; } char *sepol_module_package_get_user_extra(sepol_module_package_t * p) { return p->user_extra; } size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p) { return p->user_extra_len; } char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p) { return p->netfilter_contexts; } size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p) { return p->netfilter_contexts_len; } int sepol_module_package_set_file_contexts(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->file_contexts, data, len)) return -1; p->file_contexts_len = len; return 0; } int sepol_module_package_set_seusers(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->seusers, data, len)) return -1; p->seusers_len = len; return 0; } int sepol_module_package_set_user_extra(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->user_extra, data, len)) return -1; p->user_extra_len = len; return 0; } int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->netfilter_contexts, data, len)) return -1; p->netfilter_contexts_len = len; return 0; } sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p) { return p->policy; } /* Append each of the file contexts from each module to the base * policy's file context. 'base_context' will be reallocated to a * larger size (and thus it is an in/out reference * variable). 'base_fc_len' is the length of base's file context; it * too is a reference variable. Return 0 on success, -1 if out of * memory. */ static int link_file_contexts(sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules) { size_t fc_len; int i; char *s; fc_len = base->file_contexts_len; for (i = 0; i < num_modules; i++) { fc_len += modules[i]->file_contexts_len; } if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) { return -1; } base->file_contexts = s; for (i = 0; i < num_modules; i++) { memcpy(base->file_contexts + base->file_contexts_len, modules[i]->file_contexts, modules[i]->file_contexts_len); base->file_contexts_len += modules[i]->file_contexts_len; } return 0; } /* Append each of the netfilter contexts from each module to the base * policy's netfilter context. 'base_context' will be reallocated to a * larger size (and thus it is an in/out reference * variable). 'base_nc_len' is the length of base's netfilter contexts; it * too is a reference variable. Return 0 on success, -1 if out of * memory. */ static int link_netfilter_contexts(sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules) { size_t base_nc_len; int i; char *base_context; base_nc_len = base->netfilter_contexts_len; for (i = 0; i < num_modules; i++) { base_nc_len += modules[i]->netfilter_contexts_len; } if ((base_context = (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) { return -1; } base->netfilter_contexts = base_context; for (i = 0; i < num_modules; i++) { memcpy(base->netfilter_contexts + base->netfilter_contexts_len, modules[i]->netfilter_contexts, modules[i]->netfilter_contexts_len); base->netfilter_contexts_len += modules[i]->netfilter_contexts_len; } return 0; } /* Links the module packages into the base. Returns 0 on success, -1 * if a requirement was not met, or -2 for all other errors. */ int sepol_link_packages(sepol_handle_t * handle, sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules, int verbose) { policydb_t **mod_pols = NULL; int i, retval; if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) { ERR(handle, "Out of memory!"); return -2; } for (i = 0; i < num_modules; i++) { mod_pols[i] = &modules[i]->policy->p; } retval = link_modules(handle, &base->policy->p, mod_pols, num_modules, verbose); free(mod_pols); if (retval == -3) { return -1; } else if (retval < 0) { return -2; } if (link_file_contexts(base, modules, num_modules) == -1) { ERR(handle, "Out of memory!"); return -2; } if (link_netfilter_contexts(base, modules, num_modules) == -1) { ERR(handle, "Out of memory!"); return -2; } return 0; } /* buf must be large enough - no checks are performed */ #define _read_helper_bufsize BUFSIZ static int read_helper(char *buf, struct policy_file *file, uint32_t bytes) { uint32_t offset, nel, read_len; int rc; offset = 0; nel = bytes; while (nel) { if (nel < _read_helper_bufsize) read_len = nel; else read_len = _read_helper_bufsize; rc = next_entry(&buf[offset], file, read_len); if (rc < 0) return -1; offset += read_len; nel -= read_len; } return 0; } #define MAXSECTIONS 100 /* Get the section offsets from a package file, offsets will be malloc'd to * the appropriate size and the caller must free() them */ static int module_package_read_offsets(sepol_module_package_t * mod, struct policy_file *file, size_t ** offsets, uint32_t * sections) { uint32_t *buf = NULL, nsec; unsigned i; size_t *off = NULL; int rc; buf = malloc(sizeof(uint32_t)*3); if (!buf) { ERR(file->handle, "out of memory"); goto err; } rc = next_entry(buf, file, sizeof(uint32_t) * 3); if (rc < 0) { ERR(file->handle, "module package header truncated"); goto err; } if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) { ERR(file->handle, "wrong magic number for module package: expected %#08x, got %#08x", SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0])); goto err; } mod->version = le32_to_cpu(buf[1]); nsec = *sections = le32_to_cpu(buf[2]); if (nsec > MAXSECTIONS) { ERR(file->handle, "too many sections (%u) in module package", nsec); goto err; } off = (size_t *) malloc((nsec + 1) * sizeof(size_t)); if (!off) { ERR(file->handle, "out of memory"); goto err; } free(buf); buf = malloc(sizeof(uint32_t) * nsec); if (!buf) { ERR(file->handle, "out of memory"); goto err; } rc = next_entry(buf, file, sizeof(uint32_t) * nsec); if (rc < 0) { ERR(file->handle, "module package offset array truncated"); goto err; } for (i = 0; i < nsec; i++) { off[i] = le32_to_cpu(buf[i]); if (i && off[i] < off[i - 1]) { ERR(file->handle, "offsets are not increasing (at %u, " "offset %zu -> %zu", i, off[i - 1], off[i]); goto err; } } rc = policy_file_length(file, &off[nsec]); if (rc < 0) goto err; if (nsec && off[nsec] < off[nsec-1]) { ERR(file->handle, "offset greater than file size (at %u, " "offset %zu -> %zu", nsec, off[nsec - 1], off[nsec]); goto err; } *offsets = off; free(buf); return 0; err: free(buf); free(off); return -1; } /* Flags for which sections have been seen during parsing of module package. */ #define SEEN_MOD 1 #define SEEN_FC 2 #define SEEN_SEUSER 4 #define SEEN_USER_EXTRA 8 #define SEEN_NETFILTER 16 int sepol_module_package_read(sepol_module_package_t * mod, struct sepol_policy_file *spf, int verbose) { struct policy_file *file = &spf->pf; uint32_t buf[1], nsec; size_t *offsets, len; int rc; unsigned i, seen = 0; if (module_package_read_offsets(mod, file, &offsets, &nsec)) return -1; /* we know the section offsets, seek to them and read in the data */ for (i = 0; i < nsec; i++) { if (policy_file_seek(file, offsets[i])) { ERR(file->handle, "error seeking to offset %zu for " "module package section %u", offsets[i], i); goto cleanup; } len = offsets[i + 1] - offsets[i]; if (len < sizeof(uint32_t)) { ERR(file->handle, "module package section %u " "has too small length %zu", i, len); goto cleanup; } /* read the magic number, so that we know which function to call */ rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "module package section %u truncated, lacks magic number", i); goto cleanup; } switch (le32_to_cpu(buf[0])) { case SEPOL_PACKAGE_SECTION_FC: if (seen & SEEN_FC) { ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i); goto cleanup; } mod->file_contexts_len = len - sizeof(uint32_t); mod->file_contexts = (char *)malloc(mod->file_contexts_len); if (!mod->file_contexts) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->file_contexts, file, mod->file_contexts_len)) { ERR(file->handle, "invalid file contexts section at section %u", i); free(mod->file_contexts); mod->file_contexts = NULL; goto cleanup; } seen |= SEEN_FC; break; case SEPOL_PACKAGE_SECTION_SEUSER: if (seen & SEEN_SEUSER) { ERR(file->handle, "found multiple seuser sections in module package (at section %u)", i); goto cleanup; } mod->seusers_len = len - sizeof(uint32_t); mod->seusers = (char *)malloc(mod->seusers_len); if (!mod->seusers) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper(mod->seusers, file, mod->seusers_len)) { ERR(file->handle, "invalid seuser section at section %u", i); free(mod->seusers); mod->seusers = NULL; goto cleanup; } seen |= SEEN_SEUSER; break; case SEPOL_PACKAGE_SECTION_USER_EXTRA: if (seen & SEEN_USER_EXTRA) { ERR(file->handle, "found multiple user_extra sections in module package (at section %u)", i); goto cleanup; } mod->user_extra_len = len - sizeof(uint32_t); mod->user_extra = (char *)malloc(mod->user_extra_len); if (!mod->user_extra) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->user_extra, file, mod->user_extra_len)) { ERR(file->handle, "invalid user_extra section at section %u", i); free(mod->user_extra); mod->user_extra = NULL; goto cleanup; } seen |= SEEN_USER_EXTRA; break; case SEPOL_PACKAGE_SECTION_NETFILTER: if (seen & SEEN_NETFILTER) { ERR(file->handle, "found multiple netfilter contexts sections in module package (at section %u)", i); goto cleanup; } mod->netfilter_contexts_len = len - sizeof(uint32_t); mod->netfilter_contexts = (char *)malloc(mod->netfilter_contexts_len); if (!mod->netfilter_contexts) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->netfilter_contexts, file, mod->netfilter_contexts_len)) { ERR(file->handle, "invalid netfilter contexts section at section %u", i); free(mod->netfilter_contexts); mod->netfilter_contexts = NULL; goto cleanup; } seen |= SEEN_NETFILTER; break; case POLICYDB_MOD_MAGIC: if (seen & SEEN_MOD) { ERR(file->handle, "found multiple module sections in module package (at section %u)", i); goto cleanup; } /* seek back to where the magic number was */ if (policy_file_seek(file, offsets[i])) goto cleanup; rc = policydb_read(&mod->policy->p, file, verbose); if (rc < 0) { ERR(file->handle, "invalid module in module package (at section %u)", i); goto cleanup; } seen |= SEEN_MOD; break; default: /* unknown section, ignore */ ERR(file->handle, "unknown magic number at section %u, offset: %zx, number: %x ", i, offsets[i], le32_to_cpu(buf[0])); break; } } if ((seen & SEEN_MOD) == 0) { ERR(file->handle, "missing module in module package"); goto cleanup; } free(offsets); return 0; cleanup: free(offsets); return -1; } int sepol_module_package_info(struct sepol_policy_file *spf, int *type, char **name, char **version) { struct policy_file *file = &spf->pf; sepol_module_package_t *mod = NULL; uint32_t buf[5], len, nsec; size_t *offsets = NULL; unsigned i, seen = 0; char *id; int rc; if (sepol_module_package_create(&mod)) return -1; if (module_package_read_offsets(mod, file, &offsets, &nsec)) { goto cleanup; } for (i = 0; i < nsec; i++) { if (policy_file_seek(file, offsets[i])) { ERR(file->handle, "error seeking to offset " "%zu for module package section %u", offsets[i], i); goto cleanup; } len = offsets[i + 1] - offsets[i]; if (len < sizeof(uint32_t)) { ERR(file->handle, "module package section %u has too small length %u", i, len); goto cleanup; } /* read the magic number, so that we know which function to call */ rc = next_entry(buf, file, sizeof(uint32_t) * 2); if (rc < 0) { ERR(file->handle, "module package section %u truncated, lacks magic number", i); goto cleanup; } switch (le32_to_cpu(buf[0])) { case SEPOL_PACKAGE_SECTION_FC: /* skip file contexts */ if (seen & SEEN_FC) { ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_FC; break; case SEPOL_PACKAGE_SECTION_SEUSER: /* skip seuser */ if (seen & SEEN_SEUSER) { ERR(file->handle, "found seuser sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_SEUSER; break; case SEPOL_PACKAGE_SECTION_USER_EXTRA: /* skip user_extra */ if (seen & SEEN_USER_EXTRA) { ERR(file->handle, "found user_extra sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_USER_EXTRA; break; case SEPOL_PACKAGE_SECTION_NETFILTER: /* skip netfilter contexts */ if (seen & SEEN_NETFILTER) { ERR(file->handle, "found multiple netfilter contexts sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_NETFILTER; break; case POLICYDB_MOD_MAGIC: if (seen & SEEN_MOD) { ERR(file->handle, "found multiple module sections in module package (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[1]); if (len != strlen(POLICYDB_MOD_STRING)) { ERR(file->handle, "module string length is wrong (at section %u)", i); goto cleanup; } /* skip id */ id = malloc(len + 1); if (!id) { ERR(file->handle, "out of memory (at section %u)", i); goto cleanup; } rc = next_entry(id, file, len); free(id); if (rc < 0) { ERR(file->handle, "cannot get module string (at section %u)", i); goto cleanup; } rc = next_entry(buf, file, sizeof(uint32_t) * 5); if (rc < 0) { ERR(file->handle, "cannot get module header (at section %u)", i); goto cleanup; } *type = le32_to_cpu(buf[0]); /* if base - we're done */ if (*type == POLICY_BASE) { *name = NULL; *version = NULL; seen |= SEEN_MOD; break; } else if (*type != POLICY_MOD) { ERR(file->handle, "module has invalid type %d (at section %u)", *type, i); goto cleanup; } /* read the name and version */ rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "cannot get module name len (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[0]); if (str_read(name, file, len)) { ERR(file->handle, "%s", strerror(errno)); goto cleanup; } rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "cannot get module version len (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[0]); if (str_read(version, file, len)) { ERR(file->handle, "%s", strerror(errno)); goto cleanup; } seen |= SEEN_MOD; break; default: break; } } if ((seen & SEEN_MOD) == 0) { ERR(file->handle, "missing module in module package"); goto cleanup; } sepol_module_package_free(mod); free(offsets); return 0; cleanup: sepol_module_package_free(mod); free(offsets); return -1; } static int write_helper(char *data, size_t len, struct policy_file *file) { int idx = 0; size_t len2; while (len) { if (len > BUFSIZ) len2 = BUFSIZ; else len2 = len; if (put_entry(&data[idx], 1, len2, file) != len2) { return -1; } len -= len2; idx += len2; } return 0; } int sepol_module_package_write(sepol_module_package_t * p, struct sepol_policy_file *spf) { struct policy_file *file = &spf->pf; policy_file_t polfile; uint32_t buf[5], offsets[5], len, nsec = 0; int i; if (p->policy) { /* compute policy length */ policy_file_init(&polfile); polfile.type = PF_LEN; polfile.handle = file->handle; if (policydb_write(&p->policy->p, &polfile)) return -1; len = polfile.len; if (!polfile.len) return -1; nsec++; } else { /* We don't support writing a package without a module at this point */ return -1; } /* seusers and user_extra only supported in base at the moment */ if ((p->seusers || p->user_extra) && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) { ERR(file->handle, "seuser and user_extra sections only supported in base"); return -1; } if (p->file_contexts) nsec++; if (p->seusers) nsec++; if (p->user_extra) nsec++; if (p->netfilter_contexts) nsec++; buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC); buf[1] = cpu_to_le32(p->version); buf[2] = cpu_to_le32(nsec); if (put_entry(buf, sizeof(uint32_t), 3, file) != 3) return -1; /* calculate offsets */ offsets[0] = (nsec + 3) * sizeof(uint32_t); buf[0] = cpu_to_le32(offsets[0]); i = 1; if (p->file_contexts) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); /* add a uint32_t to compensate for the magic number */ len = p->file_contexts_len + sizeof(uint32_t); i++; } if (p->seusers) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->seusers_len + sizeof(uint32_t); i++; } if (p->user_extra) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->user_extra_len + sizeof(uint32_t); i++; } if (p->netfilter_contexts) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->netfilter_contexts_len + sizeof(uint32_t); i++; } if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec) return -1; /* write sections */ if (policydb_write(&p->policy->p, file)) return -1; if (p->file_contexts) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->file_contexts, p->file_contexts_len, file)) return -1; } if (p->seusers) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->seusers, p->seusers_len, file)) return -1; } if (p->user_extra) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->user_extra, p->user_extra_len, file)) return -1; } if (p->netfilter_contexts) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper (p->netfilter_contexts, p->netfilter_contexts_len, file)) return -1; } return 0; } int sepol_link_modules(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t ** modules, size_t len, int verbose) { return link_modules(handle, &base->p, (policydb_t **) modules, len, verbose); } int sepol_expand_module(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t * out, int verbose, int check) { return expand_module(handle, &base->p, &out->p, verbose, check); } libsepol/src/module_internal.h0100644 0000000 0000000 00000000202 13756670065 015550 0ustar000000000 0000000 #include #include "dso.h" hidden_proto(sepol_module_package_create) hidden_proto(sepol_module_package_free) libsepol/src/module_to_cil.c0100644 0000000 0000000 00000264434 13756670065 015223 0ustar000000000 0000000 /* Authors: Steve Lawrence * * Functions to convert policy module to CIL * * Copyright (C) 2015 Tresys Technology, LLC * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kernel_to_common.h" #include "private.h" #ifdef __GNUC__ # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define UNUSED(x) UNUSED_ ## x #endif FILE *out_file; #define STACK_SIZE 16 #define DEFAULT_LEVEL "systemlow" #define DEFAULT_OBJECT "object_r" #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/cil/src/cil_post.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/cil/src/cil_post.c */ #define ROLEATTR_INFIX "_roleattr_" __attribute__ ((format(printf, 1, 2))) static void log_err(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(stderr, fmt, argptr) < 0) { _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(stderr, "\n") < 0) { _exit(EXIT_FAILURE); } } static void cil_indent(int indent) { if (fprintf(out_file, "%*s", indent * 4, "") < 0) { log_err("Failed to write to output"); _exit(EXIT_FAILURE); } } __attribute__ ((format(printf, 1, 2))) static void cil_printf(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { log_err("Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); } __attribute__ ((format(printf, 2, 3))) static void cil_println(int indent, const char *fmt, ...) { cil_indent(indent); va_list argptr; va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { log_err("Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(out_file, "\n") < 0) { log_err("Failed to write to output"); _exit(EXIT_FAILURE); } } static int get_line(char **start, char *end, char **line) { int rc = 1; char *p = NULL; size_t len = 0; *line = NULL; for (p = *start; p < end && isspace(*p); p++); *start = p; for (len = 0; p < end && *p != '\n' && *p != '\0'; p++, len++); if (zero_or_saturated(len)) { rc = 0; goto exit; } *line = malloc(len+1); if (*line == NULL) { log_err("Out of memory"); rc = -1; goto exit; } memcpy(*line, *start, len); (*line)[len] = '\0'; *start = p; return rc; exit: *start = NULL; return rc; } struct map_args { struct policydb *pdb; struct avrule_block *block; struct stack *decl_stack; int scope; int indent; int sym_index; }; struct stack { void **stack; int pos; int size; }; struct role_list_node { char *role_name; role_datum_t *role; }; struct attr_list_node { char *attr_name; int is_type; void *set; }; struct list_node { void *data; struct list_node *next; }; struct list { struct list_node *head; }; /* A linked list of all roles stored in the pdb * which is iterated to determine types associated * with each role when printing role_type statements */ static struct list *role_list; static void list_destroy(struct list **list) { struct list_node *curr = (*list)->head; struct list_node *tmp; while (curr != NULL) { tmp = curr->next; free(curr); curr = tmp; } free(*list); *list = NULL; } static void role_list_destroy(void) { struct list_node *curr; if (role_list == NULL) { return; } curr = role_list->head; while (curr != NULL) { free(curr->data); curr->data = NULL; curr = curr->next; } list_destroy(&role_list); } static void attr_list_destroy(struct list **attr_list) { if (attr_list == NULL || *attr_list == NULL) { return; } struct list_node *curr = (*attr_list)->head; struct attr_list_node *attr; while (curr != NULL) { attr = curr->data; if (attr != NULL) { free(attr->attr_name); } free(curr->data); curr->data = NULL; curr = curr->next; } list_destroy(attr_list); } static int list_init(struct list **list) { struct list *l = calloc(1, sizeof(*l)); if (l == NULL) { return -1; } *list = l; return 0; } static int list_prepend(struct list *list, void *data) { int rc = -1; struct list_node *node = calloc(1, sizeof(*node)); if (node == NULL) { goto exit; } node->data = data; node->next = list->head; list->head = node; rc = 0; exit: return rc; } static int roles_gather_map(char *key, void *data, void *args) { struct role_list_node *role_node; role_datum_t *role = data; int rc = -1; role_node = calloc(1, sizeof(*role_node)); if (role_node == NULL) { return rc; } role_node->role_name = key; role_node->role = role; rc = list_prepend((struct list *)args, role_node); if (rc != 0) free(role_node); return rc; } static int role_list_create(hashtab_t roles_tab) { int rc = -1; rc = list_init(&role_list); if (rc != 0) { goto exit; } rc = hashtab_map(roles_tab, roles_gather_map, role_list); exit: return rc; } // array of lists, where each list contains all the aliases defined in the scope at index i static struct list **typealias_lists; static uint32_t typealias_lists_len; static int typealiases_gather_map(char *key, void *data, void *arg) { int rc = -1; struct type_datum *type = data; struct policydb *pdb = arg; struct scope_datum *scope; uint32_t len; uint32_t scope_id; if (type->primary != 1) { scope = hashtab_search(pdb->scope[SYM_TYPES].table, key); if (scope == NULL) { return -1; } len = scope->decl_ids_len; if (len > 0) { scope_id = scope->decl_ids[len-1]; if (typealias_lists[scope_id] == NULL) { rc = list_init(&typealias_lists[scope_id]); if (rc != 0) { goto exit; } } /* As typealias_lists[scope_id] does not hold the * ownership of its items (typealias_list_destroy does * not free the list items), "key" does not need to be * strdup'ed before it is inserted in the list. */ list_prepend(typealias_lists[scope_id], key); } } return 0; exit: return rc; } static void typealias_list_destroy(void) { uint32_t i; for (i = 0; i < typealias_lists_len; i++) { if (typealias_lists[i] != NULL) { list_destroy(&typealias_lists[i]); } } typealias_lists_len = 0; free(typealias_lists); typealias_lists = NULL; } static int typealias_list_create(struct policydb *pdb) { uint32_t max_decl_id = 0; struct avrule_decl *decl; struct avrule_block *block; uint32_t rc = -1; for (block = pdb->global; block != NULL; block = block->next) { decl = block->branch_list; if (decl != NULL && decl->decl_id > max_decl_id) { max_decl_id = decl->decl_id; } } typealias_lists = calloc(max_decl_id + 1, sizeof(*typealias_lists)); typealias_lists_len = max_decl_id + 1; rc = hashtab_map(pdb->p_types.table, typealiases_gather_map, pdb); if (rc != 0) { goto exit; } return 0; exit: typealias_list_destroy(); return rc; } static int stack_destroy(struct stack **stack) { if (stack == NULL || *stack == NULL) { return 0; } free((*stack)->stack); free(*stack); *stack = NULL; return 0; } static int stack_init(struct stack **stack) { int rc = -1; struct stack *s = calloc(1, sizeof(*s)); if (s == NULL) { goto exit; } s->stack = malloc(sizeof(*s->stack) * STACK_SIZE); if (s->stack == NULL) { goto exit; } s->pos = -1; s->size = STACK_SIZE; *stack = s; return 0; exit: stack_destroy(&s); return rc; } static int stack_push(struct stack *stack, void *ptr) { int rc = -1; void *new_stack; if (stack->pos + 1 == stack->size) { new_stack = realloc(stack->stack, sizeof(*stack->stack) * (stack->size * 2)); if (new_stack == NULL) { goto exit; } stack->stack = new_stack; stack->size *= 2; } stack->pos++; stack->stack[stack->pos] = ptr; rc = 0; exit: return rc; } static void *stack_pop(struct stack *stack) { if (stack->pos == -1) { return NULL; } stack->pos--; return stack->stack[stack->pos + 1]; } static void *stack_peek(struct stack *stack) { if (stack->pos == -1) { return NULL; } return stack->stack[stack->pos]; } static int is_id_in_scope_with_start(struct policydb *pdb, struct stack *decl_stack, int start, uint32_t symbol_type, char *id) { int i; uint32_t j; struct avrule_decl *decl; struct scope_datum *scope; scope = hashtab_search(pdb->scope[symbol_type].table, id); if (scope == NULL) { return 0; } for (i = start; i >= 0; i--) { decl = decl_stack->stack[i]; for (j = 0; j < scope->decl_ids_len; j++) { if (scope->decl_ids[j] == decl->decl_id) { return 1; } } } return 0; } static int is_id_in_ancestor_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type) { int start = decl_stack->pos - 1; return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type); } static int is_id_in_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type) { int start = decl_stack->pos; return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type); } static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct mls_semantic_level *level) { struct mls_semantic_cat *cat; cil_printf("(%s ", pdb->p_sens_val_to_name[level->sens - sens_offset]); if (level->cat != NULL) { cil_printf("("); } for (cat = level->cat; cat != NULL; cat = cat->next) { if (cat->low == cat->high) { cil_printf("%s", pdb->p_cat_val_to_name[cat->low - 1]); } else { cil_printf("range %s %s", pdb->p_cat_val_to_name[cat->low - 1], pdb->p_cat_val_to_name[cat->high - 1]); } if (cat->next != NULL) { cil_printf(" "); } } if (level->cat != NULL) { cil_printf(")"); } cil_printf(")"); return 0; } static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const struct class_perm_node *classperms) { int rc = -1; const char *rule; const struct class_perm_node *classperm; char *perms; switch (type) { case AVRULE_ALLOWED: rule = "allow"; break; case AVRULE_AUDITALLOW: rule = "auditallow"; break; case AVRULE_AUDITDENY: rule = "auditdenty"; break; case AVRULE_DONTAUDIT: rule = "dontaudit"; break; case AVRULE_NEVERALLOW: rule = "neverallow"; break; case AVRULE_TRANSITION: rule = "typetransition"; break; case AVRULE_MEMBER: rule = "typemember"; break; case AVRULE_CHANGE: rule = "typechange"; break; default: log_err("Unknown avrule type: %i", type); rc = -1; goto exit; } for (classperm = classperms; classperm != NULL; classperm = classperm->next) { if (type & AVRULE_AV) { perms = sepol_av_to_string(pdb, classperm->tclass, classperm->data); if (perms == NULL) { log_err("Failed to generate permission string"); rc = -1; goto exit; } cil_println(indent, "(%s %s %s (%s (%s)))", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], perms + 1); } else { cil_println(indent, "(%s %s %s %s %s)", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], pdb->p_type_val_to_name[classperm->data - 1]); } } return 0; exit: return rc; } #define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) static int xperms_to_cil(const av_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; unsigned int in_range = 0; int first = 1; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) return -1; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if (!first) cil_printf(" "); else first = 0; if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; cil_printf("(range 0x%hx 0x%hx)", low_value, value); in_range = 0; } else { cil_printf("0x%hx", value); } } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; cil_printf("(range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); in_range = 0; } else { cil_printf("(range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); } } } return 0; } static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const class_perm_node_t *classperms, const av_extended_perms_t *xperms) { int rc = -1; const char *rule; const struct class_perm_node *classperm; switch (type) { case AVRULE_XPERMS_ALLOWED: rule = "allowx"; break; case AVRULE_XPERMS_AUDITALLOW: rule = "auditallowx"; break; case AVRULE_XPERMS_DONTAUDIT: rule = "dontauditx"; break; case AVRULE_XPERMS_NEVERALLOW: rule = "neverallowx"; break; default: log_err("Unknown avrule xperm type: %i", type); rc = -1; goto exit; } for (classperm = classperms; classperm != NULL; classperm = classperm->next) { cil_indent(indent); cil_printf("(%s %s %s (%s %s (", rule, src, tgt, "ioctl", pdb->p_class_val_to_name[classperm->tclass - 1]); xperms_to_cil(xperms); cil_printf(")))\n"); } return 0; exit: return rc; } static int num_digits(int n) { int num = 1; while (n >= 10) { n /= 10; num++; } return num; } static int ebitmap_to_cil(struct policydb *pdb, struct ebitmap *map, int type) { struct ebitmap_node *node; uint32_t i; char **val_to_name = pdb->sym_val_to_name[type]; ebitmap_for_each_bit(map, node, i) { if (!ebitmap_get_bit(map, i)) { continue; } cil_printf("%s ", val_to_name[i]); } return 0; } static char *get_new_attr_name(struct policydb *pdb, int is_type) { static unsigned int num_attrs = 0; int len, rlen; const char *infix; char *attr_name = NULL; num_attrs++; if (is_type) { infix = TYPEATTR_INFIX; } else { infix = ROLEATTR_INFIX; } len = strlen(pdb->name) + strlen(infix) + num_digits(num_attrs) + 1; attr_name = malloc(len); if (!attr_name) { log_err("Out of memory"); goto exit; } rlen = snprintf(attr_name, len, "%s%s%i", pdb->name, infix, num_attrs); if (rlen < 0 || rlen >= len) { log_err("Failed to generate attribute name"); free(attr_name); attr_name = NULL; goto exit; } exit: return attr_name; } static int cil_add_attr_to_list(struct list *attr_list, char *attr_name, int is_type, void *set) { struct attr_list_node *attr_list_node = NULL; int rc = 0; attr_list_node = calloc(1, sizeof(*attr_list_node)); if (attr_list_node == NULL) { log_err("Out of memory"); rc = -1; goto exit; } rc = list_prepend(attr_list, attr_list_node); if (rc != 0) { goto exit; } attr_list_node->attr_name = attr_name; attr_list_node->is_type = is_type; attr_list_node->set = set; return rc; exit: free(attr_list_node); return rc; } static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, void *set, char *attr_name) { // CIL doesn't support anonymous positive/negative/complemented sets. So // instead we create a CIL type/roleattributeset that matches the set. If // the set has a negative set, then convert it to is (P & !N), where P is // the list of members in the positive set and N is the list of members // in the negative set. Additionally, if the set is complemented, then wrap // the whole thing with a negation. struct ebitmap_node *node; struct ebitmap *pos, *neg; uint32_t flags; unsigned i; struct type_set *ts; struct role_set *rs; int has_positive, has_negative; const char *kind; char **val_to_name; int rc = 0; if (is_type) { kind = "type"; val_to_name = pdb->p_type_val_to_name; ts = (struct type_set *)set; pos = &ts->types; neg = &ts->negset; flags = ts->flags; has_positive = pos && (ebitmap_length(pos) > 0); has_negative = neg && (ebitmap_length(neg) > 0); } else { kind = "role"; val_to_name = pdb->p_role_val_to_name; rs = (struct role_set *)set; pos = &rs->roles; neg = NULL; flags = rs->flags; has_positive = pos && (ebitmap_length(pos) > 0); has_negative = 0; } cil_println(indent, "(%sattribute %s)", kind, attr_name); cil_indent(indent); cil_printf("(%sattributeset %s ", kind, attr_name); if (flags & TYPE_STAR) { cil_printf("(all)"); } if (flags & TYPE_COMP) { cil_printf("(not "); } if (has_positive && has_negative) { cil_printf("(and "); } if (has_positive) { cil_printf("("); ebitmap_for_each_bit(pos, node, i) { if (!ebitmap_get_bit(pos, i)) { continue; } cil_printf("%s ", val_to_name[i]); } cil_printf(") "); } if (has_negative) { cil_printf("(not ("); ebitmap_for_each_bit(neg, node, i) { if (!ebitmap_get_bit(neg, i)) { continue; } cil_printf("%s ", val_to_name[i]); } cil_printf("))"); } if (has_positive && has_negative) { cil_printf(")"); } if (flags & TYPE_COMP) { cil_printf(")"); } cil_printf(")\n"); return rc; } static int cil_print_attr_list(int indent, struct policydb *pdb, struct list *attr_list) { struct list_node *curr; struct attr_list_node *node; int rc = 0; for (curr = attr_list->head; curr != NULL; curr = curr->next) { node = curr->data; rc = cil_print_attr_strs(indent, pdb, node->is_type, node->set, node->attr_name); if (rc != 0) { return rc; } } return rc; } static char *search_attr_list(struct list *attr_list, int is_type, void *set) { struct list_node *curr; struct attr_list_node *node; struct role_set *rs1 = NULL, *rs2; struct type_set *ts1 = NULL, *ts2; if (is_type) { ts1 = (struct type_set *)set; } else { rs1 = (struct role_set *)set; } for (curr = attr_list->head; curr != NULL; curr = curr->next) { node = curr->data; if (node->is_type != is_type) continue; if (ts1) { ts2 = (struct type_set *)node->set; if (ts1->flags != ts2->flags) continue; if (ebitmap_cmp(&ts1->negset, &ts2->negset) == 0) continue; if (ebitmap_cmp(&ts1->types, &ts2->types) == 0) continue; return node->attr_name; } else { rs2 = (struct role_set *)node->set; if (rs1->flags != rs2->flags) continue; if (ebitmap_cmp(&rs1->roles, &rs2->roles) == 0) continue; return node->attr_name; } } return NULL; } static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names) { char *attr_name = NULL; int rc = 0; *names = NULL; *num_names = 0; attr_name = search_attr_list(attr_list, is_type, set); if (!attr_name) { attr_name = get_new_attr_name(pdb, is_type); if (!attr_name) { rc = -1; goto exit; } rc = cil_add_attr_to_list(attr_list, attr_name, is_type, set); if (rc != 0) { free(attr_name); goto exit; } } *names = malloc(sizeof(char *)); if (!*names) { log_err("Out of memory"); rc = -1; goto exit; } *names[0] = attr_name; *num_names = 1; exit: return rc; } static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names) { int rc = 0; struct ebitmap_node *node; uint32_t i; uint32_t num; char **name_arr; num = 0; ebitmap_for_each_bit(map, node, i) { if (ebitmap_get_bit(map, i)) { if (num >= UINT32_MAX / sizeof(*name_arr)) { log_err("Overflow"); rc = -1; goto exit; } num++; } } if (!num) { *names = NULL; *num_names = 0; goto exit; } name_arr = malloc(sizeof(*name_arr) * num); if (name_arr == NULL) { log_err("Out of memory"); rc = -1; goto exit; } num = 0; ebitmap_for_each_bit(map, node, i) { if (ebitmap_get_bit(map, i)) { name_arr[num] = vals_to_names[i]; num++; } } *names = name_arr; *num_names = num; exit: return rc; } static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names) { int rc = 0; *names = NULL; *num_names = 0; if (rs->flags) { rc = set_to_names(pdb, 0, &rs->roles, attr_list, names, num_names); if (rc != 0) { goto exit; } } else { rc = ebitmap_to_names(&rs->roles, pdb->p_role_val_to_name, names, num_names); if (rc != 0) { goto exit; } } exit: return rc; } static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names) { int rc = 0; *names = NULL; *num_names = 0; if (ebitmap_length(&ts->negset) > 0 || ts->flags != 0) { rc = set_to_names(pdb, 1, ts, attr_list, names, num_names); if (rc != 0) { goto exit; } } else { rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, names, num_names); if (rc != 0) { goto exit; } } exit: return rc; } static void names_destroy(char ***names, int *num_names) { free(*names); *names = NULL; *num_names = 0; } static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *decl_stack, char *type_name, int indent) { struct list_node *curr; char **tnames = NULL; int num_tnames, i; struct role_list_node *role_node = NULL; int rc; struct type_set *ts; struct list *attr_list = NULL; rc = list_init(&attr_list); if (rc != 0) { goto exit; } for (curr = role_list->head; curr != NULL; curr = curr->next) { role_node = curr->data; if (!is_id_in_ancestor_scope(pdb, decl_stack, role_node->role_name, SYM_ROLES)) { continue; } ts = &role_node->role->types; rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); if (rc != 0) { goto exit; } for (i = 0; i < num_tnames; i++) { if (!strcmp(type_name, tnames[i])) { cil_println(indent, "(roletype %s %s)", role_node->role_name, type_name); } } names_destroy(&tnames, &num_tnames); } rc = cil_print_attr_list(indent, pdb, attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&attr_list); return rc; } static int name_list_to_string(char **names, int num_names, char **string) { // create a space separated string of the names int rc = -1; size_t len = 0; int i; char *str; char *strpos; for (i = 0; i < num_names; i++) { len += strlen(names[i]); if (len < strlen(names[i])) { log_err("Overflow"); return -1; } } // add spaces + null terminator len += num_names; if (len < (size_t)num_names) { log_err("Overflow"); return -1; } if (!len) { log_err("Empty list"); return -1; } str = malloc(len); if (str == NULL) { log_err("Out of memory"); rc = -1; goto exit; } str[0] = 0; strpos = str; for (i = 0; i < num_names; i++) { strpos = stpcpy(strpos, names[i]); if (i < num_names - 1) { *strpos++ = ' '; } } *string = str; return 0; exit: free(str); return rc; } static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *avrule_list, struct list *attr_list) { int rc = -1; struct avrule *avrule; char **snames = NULL; char **tnames = NULL; int s, t, num_snames, num_tnames; struct type_set *ts; for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) { if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && avrule->source_filename) { cil_println(0, ";;* lmx %lu %s\n",avrule->source_line, avrule->source_filename); } ts = &avrule->stypes; rc = process_typeset(pdb, ts, attr_list, &snames, &num_snames); if (rc != 0) { goto exit; } ts = &avrule->ttypes; rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); if (rc != 0) { goto exit; } for (s = 0; s < num_snames; s++) { for (t = 0; t < num_tnames; t++) { if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms); } else { rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms); } if (rc != 0) { goto exit; } } if (avrule->flags & RULE_SELF) { if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms); } else { rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms); } if (rc != 0) { goto exit; } } } names_destroy(&snames, &num_snames); names_destroy(&tnames, &num_tnames); if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && avrule->source_filename) { cil_println(0, ";;* lme\n"); } } return 0; exit: names_destroy(&snames, &num_snames); names_destroy(&tnames, &num_tnames); return rc; } static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *cond_expr, uint32_t flags) { int rc = 0; struct cond_expr *curr; struct stack *stack = NULL; int len = 0; int rlen; char *new_val = NULL; char *val1 = NULL; char *val2 = NULL; int num_params; const char *op; const char *fmt_str; const char *type; rc = stack_init(&stack); if (rc != 0) { log_err("Out of memory"); goto exit; } for (curr = cond_expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { val1 = pdb->p_bool_val_to_name[curr->bool - 1]; // length of boolean + 2 parens + null terminator len = strlen(val1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s)", val1); if (rlen < 0 || rlen >= len) { log_err("Failed to generate conditional expression"); rc = -1; goto exit; } } else { switch(curr->expr_type) { case COND_NOT: op = "not"; break; case COND_OR: op = "or"; break; case COND_AND: op = "and"; break; case COND_XOR: op = "xor"; break; case COND_EQ: op = "eq"; break; case COND_NEQ: op = "neq"; break; default: rc = -1; goto exit; } num_params = curr->expr_type == COND_NOT ? 1 : 2; if (num_params == 1) { val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { log_err("Out of memory"); rc = -1; goto exit; } fmt_str = "(%s %s)"; } else { val2 = stack_pop(stack); val1 = stack_pop(stack); fmt_str = "(%s %s %s)"; } if (val1 == NULL || val2 == NULL) { log_err("Invalid conditional expression"); rc = -1; goto exit; } // length = length of parameters + // length of operator + // 1 space preceeding each parameter + // 2 parens around the whole expression // + null terminator len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } // although we always supply val2 and there isn't always a 2nd // value, it should only be used when there are actually two values // in the format strings rlen = snprintf(new_val, len, fmt_str, op, val1, val2); if (rlen < 0 || rlen >= len) { log_err("Failed to generate conditional expression"); rc = -1; goto exit; } free(val1); free(val2); val1 = NULL; val2 = NULL; } rc = stack_push(stack, new_val); if (rc != 0) { log_err("Out of memory"); goto exit; } new_val = NULL; } if (flags & COND_NODE_FLAGS_TUNABLE) { type = "tunableif"; } else { type = "booleanif"; } val1 = stack_pop(stack); if (val1 == NULL || stack_peek(stack) != NULL) { log_err("Invalid conditional expression"); rc = -1; goto exit; } cil_println(indent, "(%s %s", type, val1); free(val1); val1 = NULL; rc = 0; exit: free(new_val); free(val1); free(val2); if (stack != NULL) { while ((val1 = stack_pop(stack)) != NULL) { free(val1); } stack_destroy(&stack); } return rc; } static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node *cond_list, struct list *attr_list) { int rc = 0; struct cond_node *cond; for (cond = cond_list; cond != NULL; cond = cond->next) { rc = cond_expr_to_cil(indent, pdb, cond->expr, cond->flags); if (rc != 0) { goto exit; } if (cond->avtrue_list != NULL) { cil_println(indent + 1, "(true"); rc = avrule_list_to_cil(indent + 2, pdb, cond->avtrue_list, attr_list); if (rc != 0) { goto exit; } cil_println(indent + 1, ")"); } if (cond->avfalse_list != NULL) { cil_println(indent + 1, "(false"); rc = avrule_list_to_cil(indent + 2, pdb, cond->avfalse_list, attr_list); if (rc != 0) { goto exit; } cil_println(indent + 1, ")"); } cil_println(indent, ")"); } exit: return rc; } static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans_rule *rules, struct list *role_attr_list, struct list *type_attr_list) { int rc = 0; struct role_trans_rule *rule; char **role_names = NULL; int num_role_names = 0; int role; char **type_names = NULL; int num_type_names = 0; int type; uint32_t i; struct ebitmap_node *node; struct type_set *ts; struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { rs = &rule->roles; rc = process_roleset(pdb, rs, role_attr_list, &role_names, &num_role_names); if (rc != 0) { goto exit; } ts = &rule->types; rc = process_typeset(pdb, ts, type_attr_list, &type_names, &num_type_names); if (rc != 0) { goto exit; } for (role = 0; role < num_role_names; role++) { for (type = 0; type < num_type_names; type++) { ebitmap_for_each_bit(&rule->classes, node, i) { if (!ebitmap_get_bit(&rule->classes, i)) { continue; } cil_println(indent, "(roletransition %s %s %s %s)", role_names[role], type_names[type], pdb->p_class_val_to_name[i], pdb->p_role_val_to_name[rule->new_role - 1]); } } } names_destroy(&role_names, &num_role_names); names_destroy(&type_names, &num_type_names); } exit: names_destroy(&role_names, &num_role_names); names_destroy(&type_names, &num_type_names); return rc; } static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allow_rule *rules, struct list *attr_list) { int rc = -1; struct role_allow_rule *rule; char **roles = NULL; int num_roles = 0; char **new_roles = NULL; int num_new_roles = 0; int i,j; struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { rs = &rule->roles; rc = process_roleset(pdb, rs, attr_list, &roles, &num_roles); if (rc != 0) { goto exit; } rs = &rule->new_roles; rc = process_roleset(pdb, rs, attr_list, &new_roles, &num_new_roles); if (rc != 0) { goto exit; } for (i = 0; i < num_roles; i++) { for (j = 0; j < num_new_roles; j++) { cil_println(indent, "(roleallow %s %s)", roles[i], new_roles[j]); } } names_destroy(&roles, &num_roles); names_destroy(&new_roles, &num_new_roles); } rc = 0; exit: names_destroy(&roles, &num_roles); names_destroy(&new_roles, &num_new_roles); return rc; } static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_trans_rule *rules, struct list *attr_list) { int rc = -1; struct range_trans_rule *rule; char **stypes = NULL; int num_stypes = 0; int stype; char **ttypes = NULL; int num_ttypes = 0; int ttype; struct ebitmap_node *node; uint32_t i; struct type_set *ts; if (!pdb->mls) { return 0; } for (rule = rules; rule != NULL; rule = rule->next) { ts = &rule->stypes; rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes); if (rc != 0) { goto exit; } ts = &rule->ttypes; rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } for (stype = 0; stype < num_stypes; stype++) { for (ttype = 0; ttype < num_ttypes; ttype++) { ebitmap_for_each_bit(&rule->tclasses, node, i) { if (!ebitmap_get_bit(&rule->tclasses, i)) { continue; } cil_indent(indent); cil_printf("(rangetransition %s %s %s ", stypes[stype], ttypes[ttype], pdb->p_class_val_to_name[i]); cil_printf("("); rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[0]); if (rc != 0) { goto exit; } cil_printf(" "); rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[1]); if (rc != 0) { goto exit; } cil_printf("))\n"); } } } names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); } rc = 0; exit: names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); return rc; } static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filename_trans_rule *rules, struct list *attr_list) { int rc = -1; char **stypes = NULL; int num_stypes = 0; int stype; char **ttypes = NULL; int num_ttypes = 0; int ttype; struct type_set *ts; struct filename_trans_rule *rule; for (rule = rules; rule != NULL; rule = rule->next) { ts = &rule->stypes; rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes); if (rc != 0) { goto exit; } ts = &rule->ttypes; rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } for (stype = 0; stype < num_stypes; stype++) { for (ttype = 0; ttype < num_ttypes; ttype++) { cil_println(indent, "(typetransition %s %s %s \"%s\" %s)", stypes[stype], ttypes[ttype], pdb->p_class_val_to_name[rule->tclass - 1], rule->name, pdb->p_type_val_to_name[rule->otype - 1]); } } names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); } rc = 0; exit: names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); return rc; } struct class_perm_datum { char *name; uint32_t val; }; struct class_perm_array { struct class_perm_datum *perms; uint32_t count; }; static int class_perm_to_array(char *key, void *data, void *args) { struct class_perm_array *arr = args; struct perm_datum *datum = data; arr->perms[arr->count].name = key; arr->perms[arr->count].val = datum->s.value; arr->count++; return 0; } static int class_perm_cmp(const void *a, const void *b) { const struct class_perm_datum *aa = a; const struct class_perm_datum *bb = b; return aa->val - bb->val; } static int common_to_cil(char *key, void *data, void *UNUSED(arg)) { int rc = -1; struct common_datum *common = data; struct class_perm_array arr; uint32_t i; arr.count = 0; arr.perms = calloc(common->permissions.nprim, sizeof(*arr.perms)); if (arr.perms == NULL) { goto exit; } rc = hashtab_map(common->permissions.table, class_perm_to_array, &arr); if (rc != 0) { goto exit; } qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp); cil_printf("(common %s (", key); for (i = 0; i < arr.count; i++) { cil_printf("%s ", arr.perms[i].name); } cil_printf("))\n"); rc = 0; exit: free(arr.perms); return rc; } static int constraint_expr_to_string(struct policydb *pdb, struct constraint_expr *exprs, char **expr_string) { int rc = -1; struct constraint_expr *expr; struct stack *stack = NULL; int len = 0; int rlen; char *new_val = NULL; char *val1 = NULL; char *val2 = NULL; uint32_t num_params; const char *op; const char *fmt_str; const char *attr1; const char *attr2; char *names = NULL; char **name_list = NULL; int num_names = 0; struct type_set *ts; rc = stack_init(&stack); if (rc != 0) { goto exit; } for (expr = exprs; expr != NULL; expr = expr->next) { if (expr->expr_type == CEXPR_ATTR || expr->expr_type == CEXPR_NAMES) { switch (expr->op) { case CEXPR_EQ: op = "eq"; break; case CEXPR_NEQ: op = "neq"; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: log_err("Unknown constraint operator type: %i", expr->op); rc = -1; goto exit; } switch (expr->attr) { case CEXPR_USER: attr1 = "u1"; attr2 = "u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 = "u2"; attr2 = ""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 = "u3"; attr2 = ""; break; case CEXPR_ROLE: attr1 = "r1"; attr2 = "r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 = "r2"; attr2 = ""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 = "r3"; attr2 = ""; break; case CEXPR_TYPE: attr1 = "t1"; attr2 = ""; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 = "t2"; attr2 = ""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 = "t3"; attr2 = ""; break; case CEXPR_L1L2: attr1 = "l1"; attr2 = "l2"; break; case CEXPR_L1H2: attr1 = "l1"; attr2 = "h2"; break; case CEXPR_H1L2: attr1 = "h1"; attr2 = "l2"; break; case CEXPR_H1H2: attr1 = "h1"; attr2 = "h2"; break; case CEXPR_L1H1: attr1 = "l1"; attr2 = "h1"; break; case CEXPR_L2H2: attr1 = "l2"; attr2 = "h2"; break; default: log_err("Unknown expression attribute type: %i", expr->attr); rc = -1; goto exit; } if (expr->expr_type == CEXPR_ATTR) { // length of values/attrs + 2 separating spaces + 2 parens + null terminator len = strlen(op) + strlen(attr1) + strlen(attr2) + 2 + 2 + 1; new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, attr2); if (rlen < 0 || rlen >= len) { log_err("Failed to generate constraint expression"); rc = -1; goto exit; } } else { if (expr->attr & CEXPR_TYPE) { ts = expr->type_names; rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } else if (expr->attr & CEXPR_USER) { rc = ebitmap_to_names(&expr->names, pdb->p_user_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } else if (expr->attr & CEXPR_ROLE) { rc = ebitmap_to_names(&expr->names, pdb->p_role_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } rc = name_list_to_string(name_list, num_names, &names); if (rc != 0) { goto exit; } // length of values/oper + 2 spaces + 2 parens + null terminator len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1; new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names); if (rlen < 0 || rlen >= len) { log_err("Failed to generate constraint expression"); rc = -1; goto exit; } names_destroy(&name_list, &num_names); free(names); names = NULL; } } else { switch (expr->expr_type) { case CEXPR_NOT: op = "not"; break; case CEXPR_AND: op = "and"; break; case CEXPR_OR: op = "or"; break; default: log_err("Unknown constraint expression type: %i", expr->expr_type); rc = -1; goto exit; } num_params = expr->expr_type == CEXPR_NOT ? 1 : 2; if (num_params == 1) { val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { log_err("Out of memory"); rc = -1; goto exit; } fmt_str = "(%s %s)"; } else { val2 = stack_pop(stack); val1 = stack_pop(stack); fmt_str = "(%s %s %s)"; } if (val1 == NULL || val2 == NULL) { log_err("Invalid constraint expression"); rc = -1; goto exit; } // length = length of parameters + // length of operator + // 1 space preceeding each parameter + // 2 parens around the whole expression // + null terminator len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } // although we always supply val2 and there isn't always a 2nd // value, it should only be used when there are actually two values // in the format strings rlen = snprintf(new_val, len, fmt_str, op, val1, val2); if (rlen < 0 || rlen >= len) { log_err("Failed to generate constraint expression"); rc = -1; goto exit; } free(val1); free(val2); val1 = NULL; val2 = NULL; } rc = stack_push(stack, new_val); if (rc != 0) { log_err("Out of memory"); goto exit; } new_val = NULL; } new_val = stack_pop(stack); if (new_val == NULL || stack_peek(stack) != NULL) { log_err("Invalid constraint expression"); rc = -1; goto exit; } *expr_string = new_val; new_val = NULL; rc = 0; exit: names_destroy(&name_list, &num_names); free(names); free(new_val); free(val1); free(val2); if (stack != NULL) { while ((val1 = stack_pop(stack)) != NULL) { free(val1); } stack_destroy(&stack); } return rc; } static int constraints_to_cil(int indent, struct policydb *pdb, char *classkey, struct class_datum *class, struct constraint_node *constraints, int is_constraint) { int rc = -1; struct constraint_node *node; char *expr = NULL; const char *mls; char *perms; mls = pdb->mls ? "mls" : ""; for (node = constraints; node != NULL; node = node->next) { rc = constraint_expr_to_string(pdb, node->expr, &expr); if (rc != 0) { goto exit; } if (is_constraint) { perms = sepol_av_to_string(pdb, class->s.value, node->permissions); cil_println(indent, "(%sconstrain (%s (%s)) %s)", mls, classkey, perms + 1, expr); } else { cil_println(indent, "(%svalidatetrans %s %s)", mls, classkey, expr); } free(expr); expr = NULL; } rc = 0; exit: free(expr); return rc; } static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { int rc = -1; struct class_datum *class = datum; const char *dflt; struct class_perm_array arr; uint32_t i; if (scope == SCOPE_REQ) { return 0; } arr.count = 0; arr.perms = calloc(class->permissions.nprim, sizeof(*arr.perms)); if (arr.perms == NULL) { goto exit; } rc = hashtab_map(class->permissions.table, class_perm_to_array, &arr); if (rc != 0) { goto exit; } qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp); cil_indent(indent); cil_printf("(class %s (", key); for (i = 0; i < arr.count; i++) { cil_printf("%s ", arr.perms[i].name); } cil_printf("))\n"); if (class->comkey != NULL) { cil_println(indent, "(classcommon %s %s)", key, class->comkey); } if (class->default_user != 0) { switch (class->default_user) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: log_err("Unknown default user value: %i", class->default_user); rc = -1; goto exit; } cil_println(indent, "(defaultuser %s %s)", key, dflt); } if (class->default_role != 0) { switch (class->default_role) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: log_err("Unknown default role value: %i", class->default_role); rc = -1; goto exit; } cil_println(indent, "(defaultrole %s %s)", key, dflt); } if (class->default_type != 0) { switch (class->default_type) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: log_err("Unknown default type value: %i", class->default_type); rc = -1; goto exit; } cil_println(indent, "(defaulttype %s %s)", key, dflt); } if (class->default_range != 0) { switch (class->default_range) { case DEFAULT_SOURCE_LOW: dflt = "source low"; break; case DEFAULT_SOURCE_HIGH: dflt = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dflt = "source low-high"; break; case DEFAULT_TARGET_LOW: dflt = "target low"; break; case DEFAULT_TARGET_HIGH: dflt = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dflt = "target low-high"; break; default: log_err("Unknown default range value: %i", class->default_range); rc = -1; goto exit; } cil_println(indent, "(defaultrange %s %s)", key, dflt); } if (class->constraints != NULL) { rc = constraints_to_cil(indent, pdb, key, class, class->constraints, 1); if (rc != 0) { goto exit; } } if (class->validatetrans != NULL) { rc = constraints_to_cil(indent, pdb, key, class, class->validatetrans, 0); if (rc != 0) { goto exit; } } rc = 0; exit: free(arr.perms); return rc; } static int class_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { struct ebitmap_node *node; uint32_t i; if (ebitmap_cardinality(&order) == 0) { return 0; } cil_indent(indent); cil_printf("(classorder ("); ebitmap_for_each_bit(&order, node, i) { if (!ebitmap_get_bit(&order, i)) { continue; } cil_printf("%s ", pdb->sym_val_to_name[SYM_CLASSES][i]); } cil_printf("))\n"); return 0; } static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope) { int rc = -1; struct ebitmap_node *node; uint32_t i; int j; char **types = NULL; int num_types = 0; struct role_datum *role = datum; struct type_set *ts; struct list *attr_list = NULL; rc = list_init(&attr_list); if (rc != 0) { goto exit; } if (scope == SCOPE_REQ) { // if a role/roleattr is in the REQ scope, then it could cause an // optional block to fail, even if it is never used. However in CIL, // symbols must be used in order to cause an optional block to fail. So // for symbols in the REQ scope, add them to a roleattribute as a way // to 'use' them in the optional without affecting the resulting policy. cil_println(indent, "(roleattributeset " GEN_REQUIRE_ATTR " %s)", key); } switch (role->flavor) { case ROLE_ROLE: if (scope == SCOPE_DECL) { // Only declare certain roles if we are reading a base module. // These roles are defined in the base module and sometimes in // other non-base modules. If we generated the roles regardless of // the policy type, it would result in duplicate declarations, // which isn't allowed in CIL. Patches have been made to refpolicy // to remove these duplicate role declarations, but we need to be // backwards compatible and support older policies. Since we know // these roles are always declared in base, only print them when we // see them in the base module. If the declarations appear in a // non-base module, ignore their declarations. // // Note that this is a hack, and if a policy author does not define // one of these roles in base, the declaration will not appear in // the resulting policy, likely resulting in a compilation error in // CIL. // // To make things more complicated, the auditadm_r and secadm_r // roles could actually be in either the base module or a non-base // module, or both. So we can't rely on this same behavior. So for // these roles, don't declare them here, even if they are in a base // or non-base module. Instead we will just declare them in the // base module elsewhere. int is_base_role = (!strcmp(key, "user_r") || !strcmp(key, "staff_r") || !strcmp(key, "sysadm_r") || !strcmp(key, "system_r") || !strcmp(key, "unconfined_r")); int is_builtin_role = (!strcmp(key, "auditadm_r") || !strcmp(key, "secadm_r")); if ((is_base_role && pdb->policy_type == SEPOL_POLICY_BASE) || (!is_base_role && !is_builtin_role)) { cil_println(indent, "(role %s)", key); } } if (ebitmap_cardinality(&role->dominates) > 1) { log_err("Warning: role 'dominance' statement unsupported in CIL. Dropping from output."); } ts = &role->types; rc = process_typeset(pdb, ts, attr_list, &types, &num_types); if (rc != 0) { goto exit; } for (j = 0; j < num_types; j++) { if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) { cil_println(indent, "(roletype %s %s)", key, types[j]); } } if (role->bounds > 0) { cil_println(indent, "(rolebounds %s %s)", key, pdb->p_role_val_to_name[role->bounds - 1]); } break; case ROLE_ATTRIB: if (scope == SCOPE_DECL) { cil_println(indent, "(roleattribute %s)", key); } if (ebitmap_cardinality(&role->roles) > 0) { cil_indent(indent); cil_printf("(roleattributeset %s (", key); ebitmap_for_each_bit(&role->roles, node, i) { if (!ebitmap_get_bit(&role->roles, i)) { continue; } cil_printf("%s ", pdb->p_role_val_to_name[i]); } cil_printf("))\n"); } ts = &role->types; rc = process_typeset(pdb, ts, attr_list, &types, &num_types); if (rc != 0) { goto exit; } for (j = 0; j < num_types; j++) { if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) { cil_println(indent, "(roletype %s %s)", key, types[j]); } } break; default: log_err("Unknown role type: %i", role->flavor); rc = -1; goto exit; } rc = cil_print_attr_list(indent, pdb, attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&attr_list); names_destroy(&types, &num_types); return rc; } static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope) { int rc = -1; struct type_datum *type = datum; if (scope == SCOPE_REQ) { // if a type/typeattr is in the REQ scope, then it could cause an // optional block to fail, even if it is never used. However in CIL, // symbols must be used in order to cause an optional block to fail. So // for symbols in the REQ scope, add them to a typeattribute as a way // to 'use' them in the optional without affecting the resulting policy. cil_println(indent, "(typeattributeset " GEN_REQUIRE_ATTR " %s)", key); } rc = roletype_role_in_ancestor_to_cil(pdb, decl_stack, key, indent); if (rc != 0) { goto exit; } switch(type->flavor) { case TYPE_TYPE: if (scope == SCOPE_DECL) { cil_println(indent, "(type %s)", key); // object_r is implicit in checkmodule, but not with CIL, // create it as part of base cil_println(indent, "(roletype " DEFAULT_OBJECT " %s)", key); } if (type->flags & TYPE_FLAGS_PERMISSIVE) { cil_println(indent, "(typepermissive %s)", key); } if (type->bounds > 0) { cil_println(indent, "(typebounds %s %s)", pdb->p_type_val_to_name[type->bounds - 1], key); } break; case TYPE_ATTRIB: if (scope == SCOPE_DECL) { cil_println(indent, "(typeattribute %s)", key); } if (type->flags & TYPE_FLAGS_EXPAND_ATTR) { cil_indent(indent); cil_printf("(expandtypeattribute (%s) ", key); if (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) { cil_printf("true"); } else if (type->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE) { cil_printf("false"); } cil_printf(")\n"); } if (ebitmap_cardinality(&type->types) > 0) { cil_indent(indent); cil_printf("(typeattributeset %s (", key); ebitmap_to_cil(pdb, &type->types, SYM_TYPES); cil_printf("))\n"); } break; case TYPE_ALIAS: break; default: log_err("Unknown flavor (%i) of type %s", type->flavor, key); rc = -1; goto exit; } rc = 0; exit: return rc; } static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct user_datum *user = datum; struct ebitmap roles = user->roles.roles; struct mls_semantic_level level = user->dfltlevel; struct mls_semantic_range range = user->range; struct ebitmap_node *node; uint32_t i; int sens_offset = 1; if (scope == SCOPE_DECL) { cil_println(indent, "(user %s)", key); // object_r is implicit in checkmodule, but not with CIL, create it // as part of base cil_println(indent, "(userrole %s " DEFAULT_OBJECT ")", key); } ebitmap_for_each_bit(&roles, node, i) { if (!ebitmap_get_bit(&roles, i)) { continue; } cil_println(indent, "(userrole %s %s)", key, pdb->p_role_val_to_name[i]); } if (block->flags & AVRULE_OPTIONAL) { // sensitivites in user statements in optionals do not have the // standard -1 offset sens_offset = 0; } cil_indent(indent); cil_printf("(userlevel %s ", key); if (pdb->mls) { semantic_level_to_cil(pdb, sens_offset, &level); } else { cil_printf(DEFAULT_LEVEL); } cil_printf(")\n"); cil_indent(indent); cil_printf("(userrange %s (", key); if (pdb->mls) { semantic_level_to_cil(pdb, sens_offset, &range.level[0]); cil_printf(" "); semantic_level_to_cil(pdb, sens_offset, &range.level[1]); } else { cil_printf(DEFAULT_LEVEL " " DEFAULT_LEVEL); } cil_printf("))\n"); return 0; } static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct cond_bool_datum *boolean = datum; const char *type; if (scope == SCOPE_DECL) { if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) { type = "tunable"; } else { type = "boolean"; } cil_println(indent, "(%s %s %s)", type, key, boolean->state ? "true" : "false"); } return 0; } static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct level_datum *level = datum; if (scope == SCOPE_DECL) { if (!level->isalias) { cil_println(indent, "(sensitivity %s)", key); } else { cil_println(indent, "(sensitivityalias %s)", key); cil_println(indent, "(sensitivityaliasactual %s %s)", key, pdb->p_sens_val_to_name[level->level->sens - 1]); } } if (ebitmap_cardinality(&level->level->cat) > 0) { cil_indent(indent); cil_printf("(sensitivitycategory %s (", key); ebitmap_to_cil(pdb, &level->level->cat, SYM_CATS); cil_printf("))\n"); } return 0; } static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { struct ebitmap_node *node; uint32_t i; if (ebitmap_cardinality(&order) == 0) { return 0; } cil_indent(indent); cil_printf("(sensitivityorder ("); ebitmap_for_each_bit(&order, node, i) { if (!ebitmap_get_bit(&order, i)) { continue; } cil_printf("%s ", pdb->p_sens_val_to_name[i]); } cil_printf("))\n"); return 0; } static int cat_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct cat_datum *cat = datum; if (scope == SCOPE_REQ) { return 0; } if (!cat->isalias) { cil_println(indent, "(category %s)", key); } else { cil_println(indent, "(categoryalias %s)", key); cil_println(indent, "(categoryaliasactual %s %s)", key, pdb->p_cat_val_to_name[cat->s.value - 1]); } return 0; } static int cat_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { int rc = -1; struct ebitmap_node *node; uint32_t i; if (ebitmap_cardinality(&order) == 0) { rc = 0; goto exit; } cil_indent(indent); cil_printf("(categoryorder ("); ebitmap_for_each_bit(&order, node, i) { if (!ebitmap_get_bit(&order, i)) { continue; } cil_printf("%s ", pdb->p_cat_val_to_name[i]); } cil_printf("))\n"); return 0; exit: return rc; } static int polcaps_to_cil(struct policydb *pdb) { int rc = -1; struct ebitmap *map; struct ebitmap_node *node; uint32_t i; const char *name; map = &pdb->policycaps; ebitmap_for_each_bit(map, node, i) { if (!ebitmap_get_bit(map, i)) { continue; } name = sepol_polcap_getname(i); if (name == NULL) { log_err("Unknown policy capability id: %i", i); rc = -1; goto exit; } cil_println(0, "(policycap %s)", name); } return 0; exit: return rc; } static int level_to_cil(struct policydb *pdb, struct mls_level *level) { struct ebitmap *map = &level->cat; cil_printf("(%s", pdb->p_sens_val_to_name[level->sens - 1]); if (ebitmap_cardinality(map) > 0) { cil_printf("("); ebitmap_to_cil(pdb, map, SYM_CATS); cil_printf(")"); } cil_printf(")"); return 0; } static int context_to_cil(struct policydb *pdb, struct context_struct *con) { cil_printf("(%s %s %s (", pdb->p_user_val_to_name[con->user - 1], pdb->p_role_val_to_name[con->role - 1], pdb->p_type_val_to_name[con->type - 1]); if (pdb->mls) { level_to_cil(pdb, &con->range.level[0]); cil_printf(" "); level_to_cil(pdb, &con->range.level[1]); } else { cil_printf(DEFAULT_LEVEL); cil_printf(" "); cil_printf(DEFAULT_LEVEL); } cil_printf("))"); return 0; } static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_string, unsigned num_sids, struct ocontext *isids) { int rc = -1; struct ocontext *isid; struct sid_item { char *sid_key; struct sid_item *next; }; struct sid_item *head = NULL; struct sid_item *item = NULL; char *sid; char unknown[18]; unsigned i; for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids) { sid = (char*)sid_to_string[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = unknown; } cil_println(0, "(sid %s)", sid); cil_printf("(sidcontext %s ", sid); context_to_cil(pdb, &isid->context[0]); cil_printf(")\n"); // get the sid names in the correct order (reverse from the isids // ocontext) for sidorder statement item = malloc(sizeof(*item)); if (item == NULL) { log_err("Out of memory"); rc = -1; goto exit; } item->sid_key = strdup(sid); item->next = head; head = item; } if (head != NULL) { cil_printf("(sidorder ("); for (item = head; item != NULL; item = item->next) { cil_printf("%s ", item->sid_key); } cil_printf("))\n"); } rc = 0; exit: while(head) { item = head; head = item->next; free(item->sid_key); free(item); } return rc; } static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *isids) { int rc = -1; rc = ocontext_isid_to_cil(pdb, selinux_sid_to_str, SELINUX_SID_SZ, isids); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int ocontext_selinux_fs_to_cil(struct policydb *UNUSED(pdb), struct ocontext *fss) { if (fss != NULL) { log_err("Warning: 'fscon' statement unsupported in CIL. Dropping from output."); } return 0; } static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *portcons) { int rc = -1; struct ocontext *portcon; const char *protocol; uint16_t high; uint16_t low; for (portcon = portcons; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { cil_printf("(portcon %s %i ", protocol, low); } else { cil_printf("(portcon %s (%i %i) ", protocol, low, high); } context_to_cil(pdb, &portcon->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb, struct ocontext *ibpkeycons) { int rc = -1; struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t high; uint16_t low; for (ibpkeycon = ibpkeycons; ibpkeycon; ibpkeycon = ibpkeycon->next) { low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { log_err("ibpkeycon subnet_prefix is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (low == high) cil_printf("(ibpkeycon %s %i ", subnet_prefix_str, low); else cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix_str, low, high); context_to_cil(pdb, &ibpkeycon->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs) { struct ocontext *netif; for (netif = netifs; netif != NULL; netif = netif->next) { cil_printf("(netifcon %s ", netif->u.name); context_to_cil(pdb, &netif->context[0]); cil_printf(" "); context_to_cil(pdb, &netif->context[1]); cil_printf(")\n"); } return 0; } static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *nodes) { int rc = -1; struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } cil_printf("(nodecon (%s) (%s) ", addr, mask); context_to_cil(pdb, &node->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *nodes) { int rc = -1; struct ocontext *node; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { log_err("Nodecon address is invalid: %s", strerror(errno)); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { log_err("Nodecon mask is invalid: %s", strerror(errno)); rc = -1; goto exit; } cil_printf("(nodecon (%s) (%s) ", addr, mask); context_to_cil(pdb, &node->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_ibendport_to_cil(struct policydb *pdb, struct ocontext *ibendports) { struct ocontext *ibendport; for (ibendport = ibendports; ibendport; ibendport = ibendport->next) { cil_printf("(ibendportcon %s %u ", ibendport->u.ibendport.dev_name, ibendport->u.ibendport.port); context_to_cil(pdb, &ibendport->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses) { int rc = -1; struct ocontext *fsuse; const char *behavior; for (fsuse = fsuses; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } cil_printf("(fsuse %s %s ", behavior, fsuse->u.name); context_to_cil(pdb, &fsuse->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_xen_isid_to_cil(struct policydb *pdb, struct ocontext *isids) { int rc = -1; rc = ocontext_isid_to_cil(pdb, xen_sid_to_str, XEN_SID_SZ, isids); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int ocontext_xen_pirq_to_cil(struct policydb *pdb, struct ocontext *pirqs) { struct ocontext *pirq; for (pirq = pirqs; pirq != NULL; pirq = pirq->next) { cil_printf("(pirqcon %i ", pirq->u.pirq); context_to_cil(pdb, &pirq->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_ioport_to_cil(struct policydb *pdb, struct ocontext *ioports) { struct ocontext *ioport; uint32_t low; uint32_t high; for (ioport = ioports; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { cil_printf("(ioportcon 0x%x ", low); } else { cil_printf("(ioportcon (0x%x 0x%x) ", low, high); } context_to_cil(pdb, &ioport->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_iomem_to_cil(struct policydb *pdb, struct ocontext *iomems) { struct ocontext *iomem; uint64_t low; uint64_t high; for (iomem = iomems; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { cil_printf("(iomemcon 0x%"PRIx64" ", low); } else { cil_printf("(iomemcon (0x%"PRIx64" 0x%"PRIx64") ", low, high); } context_to_cil(pdb, &iomem->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_pcidevice_to_cil(struct policydb *pdb, struct ocontext *pcids) { struct ocontext *pcid; for (pcid = pcids; pcid != NULL; pcid = pcid->next) { cil_printf("(pcidevicecon 0x%lx ", (unsigned long)pcid->u.device); context_to_cil(pdb, &pcid->context[0]); cil_printf(")\n"); } return 0; } static int ocontexts_to_cil(struct policydb *pdb) { int rc = -1; int ocon; static int (**ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); static int (*ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_selinux_isid_to_cil, ocontext_selinux_fs_to_cil, ocontext_selinux_port_to_cil, ocontext_selinux_netif_to_cil, ocontext_selinux_node_to_cil, ocontext_selinux_fsuse_to_cil, ocontext_selinux_node6_to_cil, ocontext_selinux_ibpkey_to_cil, ocontext_selinux_ibendport_to_cil, }; static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_xen_isid_to_cil, ocontext_xen_pirq_to_cil, ocontext_xen_ioport_to_cil, ocontext_xen_iomem_to_cil, ocontext_xen_pcidevice_to_cil, NULL, NULL, }; switch (pdb->target_platform) { case SEPOL_TARGET_SELINUX: ocon_funcs = ocon_selinux_funcs; break; case SEPOL_TARGET_XEN: ocon_funcs = ocon_xen_funcs; break; default: log_err("Unknown target platform: %i", pdb->target_platform); rc = -1; goto exit; } for (ocon = 0; ocon < OCON_NUM; ocon++) { if (ocon_funcs[ocon] != NULL) { rc = ocon_funcs[ocon](pdb, pdb->ocontexts[ocon]); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int genfscon_to_cil(struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name); context_to_cil(pdb, &ocon->context[0]); cil_printf(")\n"); } } return 0; } static int level_string_to_cil(char *levelstr) { int rc = -1; char *sens = NULL; char *cats = NULL; int matched; char *saveptr = NULL; char *token = NULL; char *ranged = NULL; matched = tokenize(levelstr, ':', 2, &sens, &cats); if (matched < 1 || matched > 2) { log_err("Invalid level: %s", levelstr); rc = -1; goto exit; } cil_printf("(%s", sens); if (matched == 2) { cil_printf("("); token = strtok_r(cats, ",", &saveptr); while (token != NULL) { ranged = strchr(token, '.'); if (ranged == NULL) { cil_printf("%s ", token); } else { *ranged = '\0'; cil_printf("(range %s %s) ", token, ranged + 1); } token = strtok_r(NULL, ",", &saveptr); } cil_printf(")"); } cil_printf(")"); rc = 0; exit: free(sens); free(cats); return rc; } static int level_range_string_to_cil(char *levelrangestr) { char *ranged = NULL; char *low; char *high; ranged = strchr(levelrangestr, '-'); if (ranged == NULL) { low = high = levelrangestr; } else { *ranged = '\0'; low = levelrangestr; high = ranged + 1; } level_string_to_cil(low); cil_printf(" "); level_string_to_cil(high); return 0; } static int context_string_to_cil(char *contextstr) { int rc = -1; int matched; char *user = NULL; char *role = NULL; char *type = NULL; char *level = NULL; matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level); if (matched < 3 || matched > 4) { log_err("Invalid context: %s", contextstr); rc = -1; goto exit; } cil_printf("(%s %s %s (", user, role, type); if (matched == 3) { cil_printf(DEFAULT_LEVEL); cil_printf(" "); cil_printf(DEFAULT_LEVEL); } else { level_range_string_to_cil(level); } cil_printf("))"); rc = 0; exit: free(user); free(role); free(type); free(level); return rc; } static int seusers_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *seusers = sepol_module_package_get_seusers(mod_pkg); size_t seusers_len = sepol_module_package_get_seusers_len(mod_pkg); char *cur = seusers; char *end = seusers + seusers_len; char *line = NULL; char *user = NULL; char *seuser = NULL; char *level = NULL; char *tmp = NULL; int matched; if (seusers_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ':', 3, &user, &seuser, &level); if (matched < 2 || matched > 3) { log_err("Invalid seuser line: %s", line); rc = -1; goto exit; } if (!strcmp(user, "__default__")) { cil_printf("(selinuxuserdefault %s (", seuser); } else { cil_printf("(selinuxuser %s %s (", user, seuser); } switch (matched) { case 2: cil_printf("systemlow systemlow"); break; case 3: level_range_string_to_cil(level); break; } cil_printf("))\n"); free(user); free(seuser); free(level); free(line); user = seuser = level = NULL; } if (rc == -1) { cil_printf("Failed to read seusers\n"); goto exit; } rc = 0; exit: free(line); free(user); free(seuser); free(level); return rc; } static int netfilter_contexts_to_cil(struct sepol_module_package *mod_pkg) { size_t netcons_len = sepol_module_package_get_netfilter_contexts_len(mod_pkg); if (netcons_len > 0) { log_err("Warning: netfilter_contexts are unsupported in CIL. Dropping from output."); } return 0; } static int user_extra_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *userx = sepol_module_package_get_user_extra(mod_pkg); size_t userx_len = sepol_module_package_get_user_extra_len(mod_pkg); char *cur = userx; char *end = userx + userx_len; char *line; int matched; char *user = NULL; char *prefix = NULL; int prefix_len = 0; char *user_str = NULL; char *prefix_str = NULL; char *eol = NULL; char *tmp = NULL; if (userx_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix); if (matched != 4) { rc = -1; log_err("Invalid user extra line: %s", line); goto exit; } prefix_len = strlen(prefix); eol = prefix + prefix_len - 1; if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) { rc = -1; log_err("Invalid user extra line: %s", line); goto exit; } *eol = '\0'; cil_println(0, "(userprefix %s %s)", user, prefix); free(user); free(prefix); free(line); free(user_str); free(prefix_str); user = prefix = line = user_str = prefix_str = NULL; } if (rc == -1) { cil_printf("Failed to read user_extra\n"); goto exit; } rc = 0; exit: free(line); free(user); free(prefix); return rc; } static int file_contexts_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *fc = sepol_module_package_get_file_contexts(mod_pkg); size_t fc_len = sepol_module_package_get_file_contexts_len(mod_pkg); char *cur = fc; char *end = fc + fc_len; char *line = NULL; int matched; char *regex = NULL; char *mode = NULL; char *context = NULL; const char *cilmode; char *tmp = NULL; if (fc_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ' ', 3, ®ex, &mode, &context); if (matched < 2 || matched > 3) { rc = -1; log_err("Invalid file context line: %s", line); goto exit; } if (matched == 2) { context = mode; mode = NULL; } if (mode == NULL) { cilmode = "any"; } else if (!strcmp(mode, "--")) { cilmode = "file"; } else if (!strcmp(mode, "-d")) { cilmode = "dir"; } else if (!strcmp(mode, "-c")) { cilmode = "char"; } else if (!strcmp(mode, "-b")) { cilmode = "block"; } else if (!strcmp(mode, "-s")) { cilmode = "socket"; } else if (!strcmp(mode, "-p")) { cilmode = "pipe"; } else if (!strcmp(mode, "-l")) { cilmode = "symlink"; } else { rc = -1; log_err("Invalid mode in file context line: %s", line); goto exit; } cil_printf("(filecon \"%s\" %s ", regex, cilmode); if (!strcmp(context, "<>")) { cil_printf("()"); } else { context_string_to_cil(context); } cil_printf(")\n"); free(regex); free(mode); free(context); free(line); regex = mode = context = line = NULL; } if (rc == -1) { cil_printf("Failed to read file_contexts_to_cil\n"); goto exit; } rc = 0; exit: free(line); free(regex); free(mode); free(context); return rc; } static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { NULL, // commons, only stored in the global symtab, handled elsewhere class_to_cil, role_to_cil, type_to_cil, user_to_cil, boolean_to_cil, sens_to_cil, cat_to_cil }; static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack) { struct type_datum *alias_datum; char *alias_name; char *type_name; struct list_node *curr; struct avrule_decl *decl = stack_peek(decl_stack); struct list *alias_list = typealias_lists[decl->decl_id]; int rc = -1; if (alias_list == NULL) { return 0; } for (curr = alias_list->head; curr != NULL; curr = curr->next) { alias_name = curr->data; alias_datum = hashtab_search(pdb->p_types.table, alias_name); if (alias_datum == NULL) { rc = -1; goto exit; } if (alias_datum->flavor == TYPE_ALIAS) { type_name = pdb->p_type_val_to_name[alias_datum->primary - 1]; } else { type_name = pdb->p_type_val_to_name[alias_datum->s.value - 1]; } cil_println(indent, "(typealias %s)", alias_name); cil_println(indent, "(typealiasactual %s %s)", alias_name, type_name); } return 0; exit: return rc; } static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct ebitmap map; struct ebitmap_node *node; unsigned int i; char * key; struct scope_datum *scope; int sym; void *datum; struct avrule_decl *decl = stack_peek(decl_stack); for (sym = 0; sym < SYM_NUM; sym++) { if (func_to_cil[sym] == NULL) { continue; } map = decl->declared.scope[sym]; ebitmap_for_each_bit(&map, node, i) { if (!ebitmap_get_bit(&map, i)) { continue; } key = pdb->sym_val_to_name[sym][i]; datum = hashtab_search(pdb->symtab[sym].table, key); if (datum == NULL) { rc = -1; goto exit; } scope = hashtab_search(pdb->scope[sym].table, key); if (scope == NULL) { rc = -1; goto exit; } rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, scope->scope); if (rc != 0) { goto exit; } } if (sym == SYM_CATS) { rc = cat_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } if (sym == SYM_LEVELS) { rc = sens_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } if (sym == SYM_CLASSES) { rc = class_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct ebitmap map; struct ebitmap_node *node; unsigned int i; unsigned int j; char * key; int sym; void *datum; struct avrule_decl *decl = stack_peek(decl_stack); struct scope_datum *scope_datum; for (sym = 0; sym < SYM_NUM; sym++) { if (func_to_cil[sym] == NULL) { continue; } map = decl->required.scope[sym]; ebitmap_for_each_bit(&map, node, i) { if (!ebitmap_get_bit(&map, i)) { continue; } key = pdb->sym_val_to_name[sym][i]; scope_datum = hashtab_search(pdb->scope[sym].table, key); if (scope_datum == NULL) { rc = -1; goto exit; } for (j = 0; j < scope_datum->decl_ids_len; j++) { if (scope_datum->decl_ids[j] == decl->decl_id) { break; } } if (j >= scope_datum->decl_ids_len) { // Symbols required in the global scope are also in the // required scope ebitmap of all avrule decls (i.e. required // in all optionals). So we need to look at the scopes of each // symbol in this avrule_decl to determine if it actually is // required in this decl, or if it's just required in the // global scope. If we got here, then this symbol is not // actually required in this scope, so skip it. continue; } datum = hashtab_search(pdb->symtab[sym].table, key); if (datum == NULL) { rc = -1; goto exit; } rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, SCOPE_REQ); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int additive_scopes_to_cil_map(char *key, void *data, void *arg) { int rc = -1; struct map_args *args = arg; rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl_stack, key, data, SCOPE_REQ); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct map_args args; args.pdb = pdb; args.block = block; args.decl_stack = decl_stack; args.indent = indent; struct avrule_decl *decl = stack_peek(decl_stack); for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) { if (func_to_cil[args.sym_index] == NULL) { continue; } rc = hashtab_map(decl->symtab[args.sym_index].table, additive_scopes_to_cil_map, &args); if (rc != 0) { goto exit; } } return 0; exit: return rc; } static int is_scope_superset(struct scope_index *sup, struct scope_index *sub) { // returns 1 if sup is a superset of sub, returns 0 otherwise int rc = 0; uint32_t i; struct ebitmap sup_map; struct ebitmap sub_map; struct ebitmap res; ebitmap_init(&res); for (i = 0; i < SYM_NUM; i++) { sup_map = sup->scope[i]; sub_map = sub->scope[i]; ebitmap_and(&res, &sup_map, &sub_map); if (!ebitmap_cmp(&res, &sub_map)) { goto exit; } ebitmap_destroy(&res); } if (sup->class_perms_len < sub->class_perms_len) { goto exit; } for (i = 0; i < sub->class_perms_len; i++) { sup_map = sup->class_perms_map[i]; sub_map = sub->class_perms_map[i]; ebitmap_and(&res, &sup_map, &sub_map); if (!ebitmap_cmp(&res, &sub_map)) { goto exit; } ebitmap_destroy(&res); } rc = 1; exit: ebitmap_destroy(&res); return rc; } static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int indent) { int rc = -1; struct avrule_decl *decl; struct list *type_attr_list = NULL; struct list *role_attr_list = NULL; decl = block->branch_list; rc = list_init(&type_attr_list); if (rc != 0) { goto exit; } rc = list_init(&role_attr_list); if (rc != 0) { goto exit; } rc = typealiases_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = declared_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = required_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = additive_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = avrule_list_to_cil(indent, pdb, decl->avrules, type_attr_list); if (rc != 0) { goto exit; } rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules, role_attr_list, type_attr_list); if (rc != 0) { goto exit; } rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules, role_attr_list); if (rc != 0) { goto exit; } rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules, type_attr_list); if (rc != 0) { goto exit; } rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules, type_attr_list); if (rc != 0) { goto exit; } rc = cond_list_to_cil(indent, pdb, decl->cond_list, type_attr_list); if (rc != 0) { goto exit; } rc = cil_print_attr_list(indent, pdb, type_attr_list); if (rc != 0) { goto exit; } rc = cil_print_attr_list(indent, pdb, role_attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&type_attr_list); attr_list_destroy(&role_attr_list); return rc; } static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int *indent) { int rc = 0; struct avrule_decl *decl; struct avrule_decl *decl_tmp; decl = block->branch_list; if (decl == NULL) { goto exit; } if (decl->next != NULL) { log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); } if (block->flags & AVRULE_OPTIONAL) { while (stack->pos > 0) { decl_tmp = stack_peek(stack); if (is_scope_superset(&decl->required, &decl_tmp->required)) { break; } stack_pop(stack); (*indent)--; cil_println(*indent, ")"); } cil_println(*indent, "(optional %s_optional_%i", pdb->name, decl->decl_id); (*indent)++; } stack_push(stack, decl); rc = block_to_cil(pdb, block, stack, *indent); if (rc != 0) { goto exit; } exit: return rc; } static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) { int rc = 0; struct avrule_decl *decl; decl = block->branch_list; if (decl == NULL) { goto exit; } if (decl->next != NULL) { log_err("Warning: 'else' not allowed in global block. Dropping from output."); } stack_push(stack, decl); // type aliases and commons are only stored in the global symtab. // However, to get scoping correct, we assume they are in the // global block rc = hashtab_map(pdb->p_commons.table, common_to_cil, NULL); if (rc != 0) { goto exit; } rc = block_to_cil(pdb, block, stack, 0); if (rc != 0) { goto exit; } exit: return rc; } static int blocks_to_cil(struct policydb *pdb) { int rc = -1; struct avrule_block *block; int indent = 0; struct stack *stack = NULL; rc = stack_init(&stack); if (rc != 0) { goto exit; } block = pdb->global; rc = global_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } for (block = block->next; block != NULL; block = block->next) { rc = module_block_to_cil(pdb, block, stack, &indent); if (rc != 0) { goto exit; } } while (indent > 0) { indent--; cil_println(indent, ")"); } exit: stack_destroy(&stack); return rc; } static int linked_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) { int rc = 0; struct avrule_decl *decl; decl = block->branch_list; if (decl == NULL) { goto exit; } if (!decl->enabled) { if (decl->next != NULL) { decl = decl->next; } else { goto exit; } } stack_push(stack, decl); rc = block_to_cil(pdb, block, stack, 0); if (rc != 0) { goto exit; } stack_pop(stack); exit: return rc; } static int linked_blocks_to_cil(struct policydb *pdb) { // Convert base module that has been linked to CIL // Since it is linked, all optional blocks have been resolved int rc = -1; struct avrule_block *block; struct stack *stack = NULL; rc = stack_init(&stack); if (rc != 0) { goto exit; } block = pdb->global; rc = global_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } for (block = block->next; block != NULL; block = block->next) { rc = linked_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } } exit: stack_destroy(&stack); return rc; } static int handle_unknown_to_cil(struct policydb *pdb) { int rc = -1; const char *hu; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: hu = "deny"; break; case SEPOL_REJECT_UNKNOWN: hu = "reject"; break; case SEPOL_ALLOW_UNKNOWN: hu = "allow"; break; default: log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); rc = -1; goto exit; } cil_println(0, "(handleunknown %s)", hu); return 0; exit: return rc; } static int generate_mls(struct policydb *pdb) { const char *mls_str = pdb->mls ? "true" : "false"; cil_println(0, "(mls %s)", mls_str); return 0; } static int generate_default_level(void) { cil_println(0, "(sensitivity s0)"); cil_println(0, "(sensitivityorder (s0))"); cil_println(0, "(level " DEFAULT_LEVEL " (s0))"); return 0; } static int generate_default_object(void) { cil_println(0, "(role " DEFAULT_OBJECT ")"); return 0; } static int generate_builtin_roles(void) { // due to inconsistentencies between policies and CIL not allowing // duplicate roles, some roles are always created, regardless of if they // are declared in modules or not cil_println(0, "(role auditadm_r)"); cil_println(0, "(role secadm_r)"); return 0; } static int generate_gen_require_attribute(void) { cil_println(0, "(typeattribute " GEN_REQUIRE_ATTR ")"); cil_println(0, "(roleattribute " GEN_REQUIRE_ATTR ")"); return 0; } static int fix_module_name(struct policydb *pdb) { char *letter; int rc = -1; // The base module doesn't have its name set, but we use that for some // autogenerated names, like optionals and attributes, to prevent naming // collisions. However, they sometimes need to be fixed up. // the base module isn't given a name, so just call it "base" if (pdb->policy_type == POLICY_BASE) { pdb->name = strdup("base"); if (pdb->name == NULL) { log_err("Out of memory"); rc = -1; goto exit; } } // CIL is more restrictive in module names than checkmodule. Convert bad // characters to underscores for (letter = pdb->name; *letter != '\0'; letter++) { if (isalnum(*letter)) { continue; } *letter = '_'; } return 0; exit: return rc; } int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked) { int rc = -1; out_file = fp; if (pdb == NULL) { rc = 0; goto exit; } if (pdb->policy_type != SEPOL_POLICY_BASE && pdb->policy_type != SEPOL_POLICY_MOD) { log_err("Policy pakcage is not a base or module"); rc = -1; goto exit; } rc = fix_module_name(pdb); if (rc != 0) { goto exit; } if (pdb->policy_type == SEPOL_POLICY_BASE && !pdb->mls) { // If this is a base non-mls policy, we need to define a default level // range that can be used for contexts by other non-mls modules, since // CIL requires that all contexts have a range, even if they are // ignored as in non-mls policies rc = generate_default_level(); if (rc != 0) { goto exit; } } if (pdb->policy_type == SEPOL_POLICY_BASE) { // object_r is implicit in checkmodule, but not with CIL, create it // as part of base rc = generate_default_object(); if (rc != 0) { goto exit; } rc = generate_builtin_roles(); if (rc != 0) { goto exit; } // default attribute to be used to mimic gen_require in CIL rc = generate_gen_require_attribute(); if (rc != 0) { goto exit; } // handle_unknown is used from only the base module rc = handle_unknown_to_cil(pdb); if (rc != 0) { goto exit; } // mls is used from only the base module rc = generate_mls(pdb); if (rc != 0) { goto exit; } } rc = role_list_create(pdb->p_roles.table); if (rc != 0) { goto exit; } rc = typealias_list_create(pdb); if (rc != 0) { goto exit; } rc = polcaps_to_cil(pdb); if (rc != 0) { goto exit; } rc = ocontexts_to_cil(pdb); if (rc != 0) { goto exit; } rc = genfscon_to_cil(pdb); if (rc != 0) { goto exit; } // now print everything that is scoped if (linked) { rc = linked_blocks_to_cil(pdb); } else { rc = blocks_to_cil(pdb); } if (rc != 0) { goto exit; } rc = 0; exit: role_list_destroy(); typealias_list_destroy(); return rc; } int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) { int rc = -1; struct sepol_policydb *pdb; out_file = fp; pdb = sepol_module_package_get_policy(mod_pkg); if (pdb == NULL) { log_err("Failed to get policydb"); rc = -1; goto exit; } rc = sepol_module_policydb_to_cil(fp, &pdb->p, 0); if (rc != 0) { goto exit; } rc = seusers_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = netfilter_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = user_extra_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = file_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = 0; exit: return rc; } static int fp_to_buffer(FILE *fp, char **data, size_t *data_len) { int rc = -1; char *d = NULL; size_t d_len = 0; size_t read_len = 0; size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files d = malloc(max_len); if (d == NULL) { log_err("Out of memory"); rc = -1; goto exit; } while ((read_len = fread(d + d_len, 1, max_len - d_len, fp)) > 0) { d_len += read_len; if (d_len == max_len) { max_len *= 2; d = realloc(d, max_len); if (d == NULL) { log_err("Out of memory"); rc = -1; goto exit; } } } if (ferror(fp) != 0) { log_err("Failed to read pp file"); rc = -1; goto exit; } *data = d; *data_len = d_len; return 0; exit: free(d); return rc; } int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg) { int rc = -1; struct sepol_policy_file *pf = NULL; struct sepol_module_package *pkg = NULL; char *data = NULL; size_t data_len; int fd; struct stat sb; rc = sepol_policy_file_create(&pf); if (rc != 0) { log_err("Failed to create policy file"); goto exit; } fd = fileno(fp); if (fstat(fd, &sb) == -1) { rc = -1; goto exit; } if (S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) { // libsepol fails when trying to read a policy package from a pipe or a // socket due its use of lseek. In this case, read the data into a // buffer and provide that to libsepol rc = fp_to_buffer(fp, &data, &data_len); if (rc != 0) { goto exit; } sepol_policy_file_set_mem(pf, data, data_len); } else { sepol_policy_file_set_fp(pf, fp); } rc = sepol_module_package_create(&pkg); if (rc != 0) { log_err("Failed to create module package"); goto exit; } rc = sepol_module_package_read(pkg, pf, 0); if (rc != 0) { log_err("Failed to read policy package"); goto exit; } *mod_pkg = pkg; exit: free(data); sepol_policy_file_free(pf); if (rc != 0) { sepol_module_package_free(pkg); } return rc; } libsepol/src/node_internal.h0100644 0000000 0000000 00000001525 13756670065 015221 0ustar000000000 0000000 #ifndef _SEPOL_NODE_INTERNAL_H_ #define _SEPOL_NODE_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_node_create) hidden_proto(sepol_node_key_free) hidden_proto(sepol_node_free) hidden_proto(sepol_node_get_con) hidden_proto(sepol_node_get_addr) hidden_proto(sepol_node_get_addr_bytes) hidden_proto(sepol_node_get_mask) hidden_proto(sepol_node_get_mask_bytes) hidden_proto(sepol_node_get_proto) hidden_proto(sepol_node_get_proto_str) hidden_proto(sepol_node_key_create) hidden_proto(sepol_node_key_unpack) hidden_proto(sepol_node_set_con) hidden_proto(sepol_node_set_addr) hidden_proto(sepol_node_set_addr_bytes) hidden_proto(sepol_node_set_mask) hidden_proto(sepol_node_set_mask_bytes) hidden_proto(sepol_node_set_proto) #endif libsepol/src/node_record.c0100644 0000000 0000000 00000032233 13756670065 014656 0ustar000000000 0000000 #include #include #include #include #include #include #include "node_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_node { /* Network address and mask */ char *addr; size_t addr_sz; char *mask; size_t mask_sz; /* Protocol */ int proto; /* Context */ sepol_context_t *con; }; struct sepol_node_key { /* Network address and mask */ char *addr; size_t addr_sz; char *mask; size_t mask_sz; /* Protocol */ int proto; }; /* Converts a string represtation (addr_str) * to a numeric representation (addr_bytes) */ static int node_parse_addr(sepol_handle_t * handle, const char *addr_str, int proto, char *addr_bytes) { switch (proto) { case SEPOL_PROTO_IP4: { struct in_addr in_addr; if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv4 address " "%s: %s", addr_str, strerror(errno)); return STATUS_ERR; } memcpy(addr_bytes, &in_addr.s_addr, 4); break; } case SEPOL_PROTO_IP6: { struct in6_addr in_addr; if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv6 address " "%s: %s", addr_str, strerror(errno)); return STATUS_ERR; } memcpy(addr_bytes, in_addr.s6_addr, 16); break; } default: ERR(handle, "unsupported protocol %u, could not " "parse address", proto); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large buffer (addr, addr_sz) * according to the protocol */ static int node_alloc_addr(sepol_handle_t * handle, int proto, char **addr, size_t * addr_sz) { char *tmp_addr = NULL; size_t tmp_addr_sz; switch (proto) { case SEPOL_PROTO_IP4: tmp_addr_sz = 4; tmp_addr = malloc(4); if (!tmp_addr) goto omem; break; case SEPOL_PROTO_IP6: tmp_addr_sz = 16; tmp_addr = malloc(16); if (!tmp_addr) goto omem; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } *addr = tmp_addr; *addr_sz = tmp_addr_sz; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(tmp_addr); ERR(handle, "could not allocate address of protocol %s", sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Converts a numeric representation (addr_bytes) * to a string representation (addr_str), according to * the protocol */ static int node_expand_addr(sepol_handle_t * handle, char *addr_bytes, int proto, char *addr_str) { switch (proto) { case SEPOL_PROTO_IP4: { struct in_addr addr; memset(&addr, 0, sizeof(struct in_addr)); memcpy(&addr.s_addr, addr_bytes, 4); if (inet_ntop(AF_INET, &addr, addr_str, INET_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv4 address to string: %s", strerror(errno)); return STATUS_ERR; } break; } case SEPOL_PROTO_IP6: { struct in6_addr addr; memset(&addr, 0, sizeof(struct in6_addr)); memcpy(&addr.s6_addr[0], addr_bytes, 16); if (inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv6 address to string: %s", strerror(errno)); return STATUS_ERR; } break; } default: ERR(handle, "unsupported protocol %u, could not" " expand address to string", proto); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large address string (addr) * according to the protocol */ static int node_alloc_addr_string(sepol_handle_t * handle, int proto, char **addr) { char *tmp_addr = NULL; switch (proto) { case SEPOL_PROTO_IP4: tmp_addr = malloc(INET_ADDRSTRLEN); if (!tmp_addr) goto omem; break; case SEPOL_PROTO_IP6: tmp_addr = malloc(INET6_ADDRSTRLEN); if (!tmp_addr) goto omem; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } *addr = tmp_addr; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(tmp_addr); ERR(handle, "could not allocate string buffer for " "address of protocol %s", sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Key */ int sepol_node_key_create(sepol_handle_t * handle, const char *addr, const char *mask, int proto, sepol_node_key_t ** key_ptr) { sepol_node_key_t *tmp_key = (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); if (!tmp_key) goto omem; if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) < 0) goto err; if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0) goto err; if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) < 0) goto err; if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0) goto err; tmp_key->proto = proto; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_node_key_free(tmp_key); ERR(handle, "could not create node key for (%s, %s, %s)", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } hidden_def(sepol_node_key_create) void sepol_node_key_unpack(const sepol_node_key_t * key, const char **addr, const char **mask, int *proto) { *addr = key->addr; *mask = key->mask; *proto = key->proto; } hidden_def(sepol_node_key_unpack) int sepol_node_key_extract(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_key_t ** key_ptr) { sepol_node_key_t *tmp_key = (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); if (!tmp_key) goto omem; tmp_key->addr = malloc(node->addr_sz); tmp_key->mask = malloc(node->mask_sz); if (!tmp_key->addr || !tmp_key->mask) goto omem; memcpy(tmp_key->addr, node->addr, node->addr_sz); memcpy(tmp_key->mask, node->mask, node->mask_sz); tmp_key->addr_sz = node->addr_sz; tmp_key->mask_sz = node->mask_sz; tmp_key->proto = node->proto; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: sepol_node_key_free(tmp_key); ERR(handle, "out of memory, could not extract node key"); return STATUS_ERR; } void sepol_node_key_free(sepol_node_key_t * key) { if (!key) return; free(key->addr); free(key->mask); free(key); } hidden_def(sepol_node_key_free) int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key) { int rc1, rc2; if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz)) return -1; else if ((node->addr_sz > key->addr_sz) || (node->mask_sz > key->mask_sz)) return 1; rc1 = memcmp(node->addr, key->addr, node->addr_sz); rc2 = memcmp(node->mask, key->mask, node->mask_sz); return (rc2 != 0) ? rc2 : rc1; } int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2) { int rc1, rc2; if ((node->addr_sz < node2->addr_sz) || (node->mask_sz < node2->mask_sz)) return -1; else if ((node->addr_sz > node2->addr_sz) || (node->mask_sz > node2->mask_sz)) return 1; rc1 = memcmp(node->addr, node2->addr, node->addr_sz); rc2 = memcmp(node->mask, node2->mask, node->mask_sz); return (rc2 != 0) ? rc2 : rc1; } /* Addr */ int sepol_node_get_addr(sepol_handle_t * handle, const sepol_node_t * node, char **addr) { char *tmp_addr = NULL; if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0) goto err; if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0) goto err; *addr = tmp_addr; return STATUS_SUCCESS; err: free(tmp_addr); ERR(handle, "could not get node address"); return STATUS_ERR; } hidden_def(sepol_node_get_addr) int sepol_node_get_addr_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **buffer, size_t * bsize) { char *tmp_buf = malloc(node->addr_sz); if (!tmp_buf) { ERR(handle, "out of memory, could not get address bytes"); return STATUS_ERR; } memcpy(tmp_buf, node->addr, node->addr_sz); *buffer = tmp_buf; *bsize = node->addr_sz; return STATUS_SUCCESS; } hidden_def(sepol_node_get_addr_bytes) int sepol_node_set_addr(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *addr) { char *tmp_addr = NULL; size_t tmp_addr_sz; if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0) goto err; if (node_parse_addr(handle, addr, proto, tmp_addr) < 0) goto err; free(node->addr); node->addr = tmp_addr; node->addr_sz = tmp_addr_sz; return STATUS_SUCCESS; err: free(tmp_addr); ERR(handle, "could not set node address to %s", addr); return STATUS_ERR; } hidden_def(sepol_node_set_addr) int sepol_node_set_addr_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *addr, size_t addr_sz) { char *tmp_addr = malloc(addr_sz); if (!tmp_addr) { ERR(handle, "out of memory, could not " "set node address"); return STATUS_ERR; } memcpy(tmp_addr, addr, addr_sz); free(node->addr); node->addr = tmp_addr; node->addr_sz = addr_sz; return STATUS_SUCCESS; } hidden_def(sepol_node_set_addr_bytes) /* Mask */ int sepol_node_get_mask(sepol_handle_t * handle, const sepol_node_t * node, char **mask) { char *tmp_mask = NULL; if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0) goto err; if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0) goto err; *mask = tmp_mask; return STATUS_SUCCESS; err: free(tmp_mask); ERR(handle, "could not get node netmask"); return STATUS_ERR; } hidden_def(sepol_node_get_mask) int sepol_node_get_mask_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **buffer, size_t * bsize) { char *tmp_buf = malloc(node->mask_sz); if (!tmp_buf) { ERR(handle, "out of memory, could not get netmask bytes"); return STATUS_ERR; } memcpy(tmp_buf, node->mask, node->mask_sz); *buffer = tmp_buf; *bsize = node->mask_sz; return STATUS_SUCCESS; } hidden_def(sepol_node_get_mask_bytes) int sepol_node_set_mask(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *mask) { char *tmp_mask = NULL; size_t tmp_mask_sz; if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0) goto err; if (node_parse_addr(handle, mask, proto, tmp_mask) < 0) goto err; free(node->mask); node->mask = tmp_mask; node->mask_sz = tmp_mask_sz; return STATUS_SUCCESS; err: free(tmp_mask); ERR(handle, "could not set node netmask to %s", mask); return STATUS_ERR; } hidden_def(sepol_node_set_mask) int sepol_node_set_mask_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *mask, size_t mask_sz) { char *tmp_mask = malloc(mask_sz); if (!tmp_mask) { ERR(handle, "out of memory, could not " "set node netmask"); return STATUS_ERR; } memcpy(tmp_mask, mask, mask_sz); free(node->mask); node->mask = tmp_mask; node->mask_sz = mask_sz; return STATUS_SUCCESS; } hidden_def(sepol_node_set_mask_bytes) /* Protocol */ int sepol_node_get_proto(const sepol_node_t * node) { return node->proto; } hidden_def(sepol_node_get_proto) void sepol_node_set_proto(sepol_node_t * node, int proto) { node->proto = proto; } hidden_def(sepol_node_set_proto) const char *sepol_node_get_proto_str(int proto) { switch (proto) { case SEPOL_PROTO_IP4: return "ipv4"; case SEPOL_PROTO_IP6: return "ipv6"; default: return "???"; } } hidden_def(sepol_node_get_proto_str) /* Create */ int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node) { sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t)); if (!tmp_node) { ERR(handle, "out of memory, could not create " "node record"); return STATUS_ERR; } tmp_node->addr = NULL; tmp_node->addr_sz = 0; tmp_node->mask = NULL; tmp_node->mask_sz = 0; tmp_node->proto = SEPOL_PROTO_IP4; tmp_node->con = NULL; *node = tmp_node; return STATUS_SUCCESS; } hidden_def(sepol_node_create) /* Deep copy clone */ int sepol_node_clone(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_t ** node_ptr) { sepol_node_t *new_node = NULL; if (sepol_node_create(handle, &new_node) < 0) goto err; /* Copy address, mask, protocol */ new_node->addr = malloc(node->addr_sz); new_node->mask = malloc(node->mask_sz); if (!new_node->addr || !new_node->mask) goto omem; memcpy(new_node->addr, node->addr, node->addr_sz); memcpy(new_node->mask, node->mask, node->mask_sz); new_node->addr_sz = node->addr_sz; new_node->mask_sz = node->mask_sz; new_node->proto = node->proto; /* Copy context */ if (node->con && (sepol_context_clone(handle, node->con, &new_node->con) < 0)) goto err; *node_ptr = new_node; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone node record"); sepol_node_free(new_node); return STATUS_ERR; } /* Destroy */ void sepol_node_free(sepol_node_t * node) { if (!node) return; sepol_context_free(node->con); free(node->addr); free(node->mask); free(node); } hidden_def(sepol_node_free) /* Context */ sepol_context_t *sepol_node_get_con(const sepol_node_t * node) { return node->con; } hidden_def(sepol_node_get_con) int sepol_node_set_con(sepol_handle_t * handle, sepol_node_t * node, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set node context"); return STATUS_ERR; } sepol_context_free(node->con); node->con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_node_set_con) libsepol/src/nodes.c0100644 0000000 0000000 00000020737 13756670065 013511 0ustar000000000 0000000 #include #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "node_internal.h" /* Create a low level node structure from * a high level representation */ static int node_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** node, const sepol_node_t * data) { ocontext_t *tmp_node = NULL; context_struct_t *tmp_con = NULL; char *addr_buf = NULL, *mask_buf = NULL; tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_node) goto omem; size_t addr_bsize, mask_bsize; /* Address and netmask */ if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0) goto err; if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0) goto err; int proto = sepol_node_get_proto(data); switch (proto) { case SEPOL_PROTO_IP4: memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize); memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize); break; case SEPOL_PROTO_IP6: memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize); memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize); break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } free(addr_buf); free(mask_buf); addr_buf = NULL; mask_buf = NULL; /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_node_get_con(data)) < 0) goto err; context_cpy(&tmp_node->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *node = tmp_node; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_node != NULL) { context_destroy(&tmp_node->context[0]); free(tmp_node); } context_destroy(tmp_con); free(tmp_con); free(addr_buf); free(mask_buf); ERR(handle, "could not create node structure"); return STATUS_ERR; } static int node_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * node, int proto, sepol_node_t ** record) { context_struct_t *con = &node->context[0]; sepol_context_t *tmp_con = NULL; sepol_node_t *tmp_record = NULL; if (sepol_node_create(handle, &tmp_record) < 0) goto err; sepol_node_set_proto(tmp_record, proto); switch (proto) { case SEPOL_PROTO_IP4: if (sepol_node_set_addr_bytes(handle, tmp_record, (const char *)&node->u.node.addr, 4) < 0) goto err; if (sepol_node_set_mask_bytes(handle, tmp_record, (const char *)&node->u.node.mask, 4) < 0) goto err; break; case SEPOL_PROTO_IP6: if (sepol_node_set_addr_bytes(handle, tmp_record, (const char *)&node->u.node6.addr, 16) < 0) goto err; if (sepol_node_set_mask_bytes(handle, tmp_record, (const char *)&node->u.node6.mask, 16) < 0) goto err; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert node to record"); sepol_context_free(tmp_con); sepol_node_free(tmp_record); return STATUS_ERR; } /* Return the number of nodes */ extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_NODE]; for (c = head; c != NULL; c = c->next) count++; head = policydb->ocontexts[OCON_NODE6]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a node exists */ int sepol_node_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_node_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); switch (proto) { case SEPOL_PROTO_IP4: { head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { unsigned int *addr2 = &c->u.node.addr; unsigned int *mask2 = &c->u.node.mask; if (!memcmp(addr, addr2, 4) && !memcmp(mask, mask2, 4)) { *response = 1; return STATUS_SUCCESS; } } break; } case SEPOL_PROTO_IP6: { head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { unsigned int *addr2 = c->u.node6.addr; unsigned int *mask2 = c->u.node6.mask; if (!memcmp(addr, addr2, 16) && !memcmp(mask, mask2, 16)) { *response = 1; return STATUS_SUCCESS; } } break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } *response = 0; return STATUS_SUCCESS; err: ERR(handle, "could not check if node %s/%s (%s) exists", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Query a node */ int sepol_node_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_node_key_t * key, sepol_node_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); switch (proto) { case SEPOL_PROTO_IP4: { head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { unsigned int *addr2 = &c->u.node.addr; unsigned int *mask2 = &c->u.node.mask; if (!memcmp(addr, addr2, 4) && !memcmp(mask, mask2, 4)) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, response) < 0) goto err; return STATUS_SUCCESS; } } break; } case SEPOL_PROTO_IP6: { head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { unsigned int *addr2 = c->u.node6.addr; unsigned int *mask2 = c->u.node6.mask; if (!memcmp(addr, addr2, 16) && !memcmp(mask, mask2, 16)) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, response) < 0) goto err; return STATUS_SUCCESS; } } break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query node %s/%s (%s)", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Load a node into policy */ int sepol_node_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_node_key_t * key, const sepol_node_t * data) { policydb_t *policydb = &p->p; ocontext_t *node = NULL; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); if (node_from_record(handle, policydb, &node, data) < 0) goto err; switch (proto) { case SEPOL_PROTO_IP4: { /* Attach to context list */ node->next = policydb->ocontexts[OCON_NODE]; policydb->ocontexts[OCON_NODE] = node; break; } case SEPOL_PROTO_IP6: { /* Attach to context list */ node->next = policydb->ocontexts[OCON_NODE6]; policydb->ocontexts[OCON_NODE6] = node; break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not load node %s/%s (%s)", addr, mask, sepol_node_get_proto_str(proto)); if (node != NULL) { context_destroy(&node->context[0]); free(node); } return STATUS_ERR; } int sepol_node_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_node_t * node, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_node_t *node = NULL; int status; head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node) < 0) goto err; /* Invoke handler */ status = fn(node, arg); if (status < 0) goto err; sepol_node_free(node); node = NULL; /* Handler requested exit */ if (status > 0) break; } head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node) < 0) goto err; /* Invoke handler */ status = fn(node, arg); if (status < 0) goto err; sepol_node_free(node); node = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over nodes"); sepol_node_free(node); return STATUS_ERR; } libsepol/src/polcaps.c0100644 0000000 0000000 00000001637 13756670065 014040 0ustar000000000 0000000 /* * Policy capability support functions */ #include #include static const char *polcap_names[] = { "network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */ "open_perms", /* POLICYDB_CAPABILITY_OPENPERM */ "extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */ "always_check_network", /* POLICYDB_CAPABILITY_ALWAYSNETWORK */ "cgroup_seclabel", /* POLICYDB_CAPABILITY_SECLABEL */ "nnp_nosuid_transition", /* POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION */ NULL }; int sepol_polcap_getnum(const char *name) { int capnum; for (capnum = 0; capnum <= POLICYDB_CAPABILITY_MAX; capnum++) { if (polcap_names[capnum] == NULL) continue; if (strcasecmp(polcap_names[capnum], name) == 0) return capnum; } return -1; } const char *sepol_polcap_getname(unsigned int capnum) { if (capnum > POLICYDB_CAPABILITY_MAX) return NULL; return polcap_names[capnum]; } libsepol/src/policydb.c0100644 0000000 0000000 00000277757 13756670065 014226 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2005 Tresys Technology, LLC * Copyright (C) 2003 - 2007 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the policy database. */ #include #include #include #include #include #include #include #include #include "kernel_to_common.h" #include "private.h" #include "debug.h" #include "mls.h" #define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings) const char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING }; /* These need to be updated if SYM_NUM or OCON_NUM changes */ static struct policydb_compat_info policydb_compat[] = { { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_XEN_PCIDEVICE + 1, .target_platform = SEPOL_TARGET_XEN, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_XEN_DEVICETREE, .sym_num = SYM_NUM, .ocon_num = OCON_XEN_DEVICETREE + 1, .target_platform = SEPOL_TARGET_XEN, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BASE, .sym_num = SYM_NUM - 3, .ocon_num = OCON_FSUSE + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOOL, .sym_num = SYM_NUM - 2, .ocon_num = OCON_FSUSE + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_IPV6, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_NLCLASS, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_AVTAB, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_RANGETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_MLS_USERS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_ROLEATTRIB, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_MLS_USERS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_ROLEATTRIB, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, }; #if 0 static char *symtab_name[SYM_NUM] = { "common prefixes", "classes", "roles", "types", "users", "bools" mls_symtab_names cond_symtab_names }; #endif static unsigned int symtab_sizes[SYM_NUM] = { 2, 32, 16, 512, 128, 16, 16, 16, }; struct policydb_compat_info *policydb_lookup_compat(unsigned int version, unsigned int type, unsigned int target_platform) { unsigned int i; struct policydb_compat_info *info = NULL; for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) { if (policydb_compat[i].version == version && policydb_compat[i].type == type && policydb_compat[i].target_platform == target_platform) { info = &policydb_compat[i]; break; } } return info; } void type_set_init(type_set_t * x) { memset(x, 0, sizeof(type_set_t)); ebitmap_init(&x->types); ebitmap_init(&x->negset); } void type_set_destroy(type_set_t * x) { if (x != NULL) { ebitmap_destroy(&x->types); ebitmap_destroy(&x->negset); } } void role_set_init(role_set_t * x) { memset(x, 0, sizeof(role_set_t)); ebitmap_init(&x->roles); } void role_set_destroy(role_set_t * x) { ebitmap_destroy(&x->roles); } void role_datum_init(role_datum_t * x) { memset(x, 0, sizeof(role_datum_t)); ebitmap_init(&x->dominates); type_set_init(&x->types); ebitmap_init(&x->cache); ebitmap_init(&x->roles); } void role_datum_destroy(role_datum_t * x) { if (x != NULL) { ebitmap_destroy(&x->dominates); type_set_destroy(&x->types); ebitmap_destroy(&x->cache); ebitmap_destroy(&x->roles); } } void type_datum_init(type_datum_t * x) { memset(x, 0, sizeof(*x)); ebitmap_init(&x->types); } void type_datum_destroy(type_datum_t * x) { if (x != NULL) { ebitmap_destroy(&x->types); } } void user_datum_init(user_datum_t * x) { memset(x, 0, sizeof(user_datum_t)); role_set_init(&x->roles); mls_semantic_range_init(&x->range); mls_semantic_level_init(&x->dfltlevel); ebitmap_init(&x->cache); mls_range_init(&x->exp_range); mls_level_init(&x->exp_dfltlevel); } void user_datum_destroy(user_datum_t * x) { if (x != NULL) { role_set_destroy(&x->roles); mls_semantic_range_destroy(&x->range); mls_semantic_level_destroy(&x->dfltlevel); ebitmap_destroy(&x->cache); mls_range_destroy(&x->exp_range); mls_level_destroy(&x->exp_dfltlevel); } } void level_datum_init(level_datum_t * x) { memset(x, 0, sizeof(level_datum_t)); } void level_datum_destroy(level_datum_t * x __attribute__ ((unused))) { /* the mls_level_t referenced by the level_datum is managed * separately for now, so there is nothing to destroy */ return; } void cat_datum_init(cat_datum_t * x) { memset(x, 0, sizeof(cat_datum_t)); } void cat_datum_destroy(cat_datum_t * x __attribute__ ((unused))) { /* it's currently a simple struct - really nothing to destroy */ return; } void class_perm_node_init(class_perm_node_t * x) { memset(x, 0, sizeof(class_perm_node_t)); } void avrule_init(avrule_t * x) { memset(x, 0, sizeof(avrule_t)); type_set_init(&x->stypes); type_set_init(&x->ttypes); } void avrule_destroy(avrule_t * x) { class_perm_node_t *cur, *next; if (x == NULL) { return; } type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); free(x->source_filename); next = x->perms; while (next) { cur = next; next = cur->next; free(cur); } free(x->xperms); } void role_trans_rule_init(role_trans_rule_t * x) { memset(x, 0, sizeof(*x)); role_set_init(&x->roles); type_set_init(&x->types); ebitmap_init(&x->classes); } void role_trans_rule_destroy(role_trans_rule_t * x) { if (x != NULL) { role_set_destroy(&x->roles); type_set_destroy(&x->types); ebitmap_destroy(&x->classes); } } void role_trans_rule_list_destroy(role_trans_rule_t * x) { while (x != NULL) { role_trans_rule_t *next = x->next; role_trans_rule_destroy(x); free(x); x = next; } } void filename_trans_rule_init(filename_trans_rule_t * x) { memset(x, 0, sizeof(*x)); type_set_init(&x->stypes); type_set_init(&x->ttypes); } static void filename_trans_rule_destroy(filename_trans_rule_t * x) { if (!x) return; type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); free(x->name); } void filename_trans_rule_list_destroy(filename_trans_rule_t * x) { filename_trans_rule_t *next; while (x) { next = x->next; filename_trans_rule_destroy(x); free(x); x = next; } } void role_allow_rule_init(role_allow_rule_t * x) { memset(x, 0, sizeof(role_allow_rule_t)); role_set_init(&x->roles); role_set_init(&x->new_roles); } void role_allow_rule_destroy(role_allow_rule_t * x) { role_set_destroy(&x->roles); role_set_destroy(&x->new_roles); } void role_allow_rule_list_destroy(role_allow_rule_t * x) { while (x != NULL) { role_allow_rule_t *next = x->next; role_allow_rule_destroy(x); free(x); x = next; } } void range_trans_rule_init(range_trans_rule_t * x) { type_set_init(&x->stypes); type_set_init(&x->ttypes); ebitmap_init(&x->tclasses); mls_semantic_range_init(&x->trange); x->next = NULL; } void range_trans_rule_destroy(range_trans_rule_t * x) { type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); ebitmap_destroy(&x->tclasses); mls_semantic_range_destroy(&x->trange); } void range_trans_rule_list_destroy(range_trans_rule_t * x) { while (x != NULL) { range_trans_rule_t *next = x->next; range_trans_rule_destroy(x); free(x); x = next; } } void avrule_list_destroy(avrule_t * x) { avrule_t *next, *cur; if (!x) return; next = x; while (next) { cur = next; next = next->next; avrule_destroy(cur); free(cur); } } /* * Initialize the role table by implicitly adding role 'object_r'. If * the policy is a module, set object_r's scope to be SCOPE_REQ, * otherwise set it to SCOPE_DECL. */ static int roles_init(policydb_t * p) { char *key = 0; int rc; role_datum_t *role; role = calloc(1, sizeof(role_datum_t)); if (!role) { rc = -ENOMEM; goto out; } key = malloc(strlen(OBJECT_R) + 1); if (!key) { rc = -ENOMEM; goto out_free_role; } strcpy(key, OBJECT_R); rc = symtab_insert(p, SYM_ROLES, key, role, (p->policy_type == POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1, &role->s.value); if (rc) goto out_free_key; if (role->s.value != OBJECT_R_VAL) { rc = -EINVAL; goto out_free_role; } out: return rc; out_free_key: free(key); out_free_role: free(role); goto out; } static inline unsigned long partial_name_hash(unsigned long c, unsigned long prevhash) { return (prevhash + (c << 4) + (c >> 4)) * 11; } static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k) { const struct filename_trans *ft = (const struct filename_trans *)k; unsigned long hash; unsigned int byte_num; unsigned char focus; hash = ft->stype ^ ft->ttype ^ ft->tclass; byte_num = 0; while ((focus = ft->name[byte_num++])) hash = partial_name_hash(focus, hash); return hash & (h->size - 1); } static int filenametr_cmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t k1, const_hashtab_key_t k2) { const struct filename_trans *ft1 = (const struct filename_trans *)k1; const struct filename_trans *ft2 = (const struct filename_trans *)k2; int v; v = ft1->stype - ft2->stype; if (v) return v; v = ft1->ttype - ft2->ttype; if (v) return v; v = ft1->tclass - ft2->tclass; if (v) return v; return strcmp(ft1->name, ft2->name); } static unsigned int rangetr_hash(hashtab_t h, const_hashtab_key_t k) { const struct range_trans *key = (const struct range_trans *)k; return (key->source_type + (key->target_type << 3) + (key->target_class << 5)) & (h->size - 1); } static int rangetr_cmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t k1, const_hashtab_key_t k2) { const struct range_trans *key1 = (const struct range_trans *)k1; const struct range_trans *key2 = (const struct range_trans *)k2; int v; v = key1->source_type - key2->source_type; if (v) return v; v = key1->target_type - key2->target_type; if (v) return v; v = key1->target_class - key2->target_class; return v; } /* * Initialize a policy database structure. */ int policydb_init(policydb_t * p) { int i, rc; memset(p, 0, sizeof(policydb_t)); for (i = 0; i < SYM_NUM; i++) { p->sym_val_to_name[i] = NULL; rc = symtab_init(&p->symtab[i], symtab_sizes[i]); if (rc) goto err; } /* initialize the module stuff */ for (i = 0; i < SYM_NUM; i++) { if (symtab_init(&p->scope[i], symtab_sizes[i])) { goto err; } } if ((p->global = avrule_block_create()) == NULL || (p->global->branch_list = avrule_decl_create(1)) == NULL) { goto err; } p->decl_val_to_struct = NULL; rc = avtab_init(&p->te_avtab); if (rc) goto err; rc = roles_init(p); if (rc) goto err; rc = cond_policydb_init(p); if (rc) goto err; p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); if (!p->filename_trans) { rc = -ENOMEM; goto err; } p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); if (!p->range_tr) { rc = -ENOMEM; goto err; } ebitmap_init(&p->policycaps); ebitmap_init(&p->permissive_map); return 0; err: hashtab_destroy(p->filename_trans); hashtab_destroy(p->range_tr); for (i = 0; i < SYM_NUM; i++) { hashtab_destroy(p->symtab[i].table); hashtab_destroy(p->scope[i].table); } avrule_block_list_destroy(p->global); return rc; } int policydb_role_cache(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { policydb_t *p; role_datum_t *role; role = (role_datum_t *) datum; p = (policydb_t *) arg; ebitmap_destroy(&role->cache); if (type_set_expand(&role->types, &role->cache, p, 1)) { return -1; } return 0; } int policydb_user_cache(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { policydb_t *p; user_datum_t *user; user = (user_datum_t *) datum; p = (policydb_t *) arg; ebitmap_destroy(&user->cache); if (role_set_expand(&user->roles, &user->cache, p, NULL, NULL)) { return -1; } /* we do not expand user's MLS info in kernel policies because the * semantic representation is not present and we do not expand user's * MLS info in module policies because all of the necessary mls * information is not present */ if (p->policy_type != POLICY_KERN && p->policy_type != POLICY_MOD) { mls_range_destroy(&user->exp_range); if (mls_semantic_range_expand(&user->range, &user->exp_range, p, NULL)) { return -1; } mls_level_destroy(&user->exp_dfltlevel); if (mls_semantic_level_expand(&user->dfltlevel, &user->exp_dfltlevel, p, NULL)) { return -1; } } return 0; } /* * The following *_index functions are used to * define the val_to_name and val_to_struct arrays * in a policy database structure. The val_to_name * arrays are used when converting security context * structures into string representations. The * val_to_struct arrays are used when the attributes * of a class, role, or user are needed. */ static int common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; common_datum_t *comdatum; comdatum = (common_datum_t *) datum; p = (policydb_t *) datap; if (!comdatum->s.value || comdatum->s.value > p->p_commons.nprim) return -EINVAL; if (p->p_common_val_to_name[comdatum->s.value - 1] != NULL) return -EINVAL; p->p_common_val_to_name[comdatum->s.value - 1] = (char *)key; return 0; } static int class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; class_datum_t *cladatum; cladatum = (class_datum_t *) datum; p = (policydb_t *) datap; if (!cladatum->s.value || cladatum->s.value > p->p_classes.nprim) return -EINVAL; if (p->p_class_val_to_name[cladatum->s.value - 1] != NULL) return -EINVAL; p->p_class_val_to_name[cladatum->s.value - 1] = (char *)key; p->class_val_to_struct[cladatum->s.value - 1] = cladatum; return 0; } static int role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; role_datum_t *role; role = (role_datum_t *) datum; p = (policydb_t *) datap; if (!role->s.value || role->s.value > p->p_roles.nprim) return -EINVAL; if (p->p_role_val_to_name[role->s.value - 1] != NULL) return -EINVAL; p->p_role_val_to_name[role->s.value - 1] = (char *)key; p->role_val_to_struct[role->s.value - 1] = role; return 0; } static int type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; type_datum_t *typdatum; typdatum = (type_datum_t *) datum; p = (policydb_t *) datap; if (typdatum->primary) { if (!typdatum->s.value || typdatum->s.value > p->p_types.nprim) return -EINVAL; if (p->p_type_val_to_name[typdatum->s.value - 1] != NULL) return -EINVAL; p->p_type_val_to_name[typdatum->s.value - 1] = (char *)key; p->type_val_to_struct[typdatum->s.value - 1] = typdatum; } return 0; } static int user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; user_datum_t *usrdatum; usrdatum = (user_datum_t *) datum; p = (policydb_t *) datap; if (!usrdatum->s.value || usrdatum->s.value > p->p_users.nprim) return -EINVAL; if (p->p_user_val_to_name[usrdatum->s.value - 1] != NULL) return -EINVAL; p->p_user_val_to_name[usrdatum->s.value - 1] = (char *)key; p->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; return 0; } static int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; level_datum_t *levdatum; levdatum = (level_datum_t *) datum; p = (policydb_t *) datap; if (!levdatum->isalias) { if (!levdatum->level->sens || levdatum->level->sens > p->p_levels.nprim) return -EINVAL; if (p->p_sens_val_to_name[levdatum->level->sens - 1] != NULL) return -EINVAL; p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *)key; } return 0; } static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; cat_datum_t *catdatum; catdatum = (cat_datum_t *) datum; p = (policydb_t *) datap; if (!catdatum->isalias) { if (!catdatum->s.value || catdatum->s.value > p->p_cats.nprim) return -EINVAL; if (p->p_cat_val_to_name[catdatum->s.value - 1] != NULL) return -EINVAL; p->p_cat_val_to_name[catdatum->s.value - 1] = (char *)key; } return 0; } static int (*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_index, class_index, role_index, type_index, user_index, cond_index_bool, sens_index, cat_index,}; /* * Define the common val_to_name array and the class * val_to_name and val_to_struct arrays in a policy * database structure. */ int policydb_index_classes(policydb_t * p) { free(p->p_common_val_to_name); p->p_common_val_to_name = (char **) calloc(p->p_commons.nprim, sizeof(char *)); if (!p->p_common_val_to_name) return -1; if (hashtab_map(p->p_commons.table, common_index, p)) return -1; free(p->class_val_to_struct); p->class_val_to_struct = (class_datum_t **) calloc(p->p_classes.nprim, sizeof(class_datum_t *)); if (!p->class_val_to_struct) return -1; free(p->p_class_val_to_name); p->p_class_val_to_name = (char **) calloc(p->p_classes.nprim, sizeof(char *)); if (!p->p_class_val_to_name) return -1; if (hashtab_map(p->p_classes.table, class_index, p)) return -1; return 0; } int policydb_index_bools(policydb_t * p) { if (cond_init_bool_indexes(p) == -1) return -1; p->p_bool_val_to_name = (char **) calloc(p->p_bools.nprim, sizeof(char *)); if (!p->p_bool_val_to_name) return -1; if (hashtab_map(p->p_bools.table, cond_index_bool, p)) return -1; return 0; } int policydb_index_decls(sepol_handle_t * handle, policydb_t * p) { avrule_block_t *curblock; avrule_decl_t *decl; unsigned int num_decls = 0; free(p->decl_val_to_struct); for (curblock = p->global; curblock != NULL; curblock = curblock->next) { for (decl = curblock->branch_list; decl != NULL; decl = decl->next) { num_decls++; } } p->decl_val_to_struct = calloc(num_decls, sizeof(*(p->decl_val_to_struct))); if (!p->decl_val_to_struct) { return -1; } for (curblock = p->global; curblock != NULL; curblock = curblock->next) { for (decl = curblock->branch_list; decl != NULL; decl = decl->next) { if (decl->decl_id < 1 || decl->decl_id > num_decls) { ERR(handle, "invalid decl ID %u", decl->decl_id); return -1; } if (p->decl_val_to_struct[decl->decl_id - 1] != NULL) { ERR(handle, "duplicated decl ID %u", decl->decl_id); return -1; } p->decl_val_to_struct[decl->decl_id - 1] = decl; } } return 0; } /* * Define the other val_to_name and val_to_struct arrays * in a policy database structure. */ int policydb_index_others(sepol_handle_t * handle, policydb_t * p, unsigned verbose) { int i; if (verbose) { INFO(handle, "security: %d users, %d roles, %d types, %d bools", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); if (p->mls) INFO(handle, "security: %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim); INFO(handle, "security: %d classes, %d rules, %d cond rules", p->p_classes.nprim, p->te_avtab.nel, p->te_cond_avtab.nel); } #if 0 avtab_hash_eval(&p->te_avtab, "rules"); for (i = 0; i < SYM_NUM; i++) hashtab_hash_eval(p->symtab[i].table, symtab_name[i]); #endif free(p->role_val_to_struct); p->role_val_to_struct = (role_datum_t **) calloc(p->p_roles.nprim, sizeof(role_datum_t *)); if (!p->role_val_to_struct) return -1; free(p->user_val_to_struct); p->user_val_to_struct = (user_datum_t **) calloc(p->p_users.nprim, sizeof(user_datum_t *)); if (!p->user_val_to_struct) return -1; free(p->type_val_to_struct); p->type_val_to_struct = (type_datum_t **) calloc(p->p_types.nprim, sizeof(type_datum_t *)); if (!p->type_val_to_struct) return -1; cond_init_bool_indexes(p); for (i = SYM_ROLES; i < SYM_NUM; i++) { free(p->sym_val_to_name[i]); p->sym_val_to_name[i] = NULL; if (p->symtab[i].nprim) { p->sym_val_to_name[i] = (char **) calloc(p->symtab[i].nprim, sizeof(char *)); if (!p->sym_val_to_name[i]) return -1; if (hashtab_map(p->symtab[i].table, index_f[i], p)) return -1; } } /* This pre-expands the roles and users for context validity checking */ if (hashtab_map(p->p_roles.table, policydb_role_cache, p)) return -1; if (hashtab_map(p->p_users.table, policydb_user_cache, p)) return -1; return 0; } /* * The following *_destroy functions are used to * free any memory allocated for each kind of * symbol data in the policy database. */ static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); free(datum); return 0; } static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { common_datum_t *comdatum; if (key) free(key); comdatum = (common_datum_t *) datum; (void)hashtab_map(comdatum->permissions.table, perm_destroy, 0); hashtab_destroy(comdatum->permissions.table); free(datum); return 0; } static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { class_datum_t *cladatum; constraint_node_t *constraint, *ctemp; constraint_expr_t *e, *etmp; if (key) free(key); cladatum = (class_datum_t *) datum; if (cladatum == NULL) { return 0; } (void)hashtab_map(cladatum->permissions.table, perm_destroy, 0); hashtab_destroy(cladatum->permissions.table); constraint = cladatum->constraints; while (constraint) { e = constraint->expr; while (e) { etmp = e; e = e->next; constraint_expr_destroy(etmp); } ctemp = constraint; constraint = constraint->next; free(ctemp); } constraint = cladatum->validatetrans; while (constraint) { e = constraint->expr; while (e) { etmp = e; e = e->next; constraint_expr_destroy(etmp); } ctemp = constraint; constraint = constraint->next; free(ctemp); } if (cladatum->comkey) free(cladatum->comkey); free(datum); return 0; } static int role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); role_datum_destroy((role_datum_t *) datum); free(datum); return 0; } static int type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); type_datum_destroy((type_datum_t *) datum); free(datum); return 0; } static int user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); user_datum_destroy((user_datum_t *) datum); free(datum); return 0; } static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { level_datum_t *levdatum; if (key) free(key); levdatum = (level_datum_t *) datum; mls_level_destroy(levdatum->level); free(levdatum->level); level_datum_destroy(levdatum); free(levdatum); return 0; } static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); cat_datum_destroy((cat_datum_t *) datum); free(datum); return 0; } static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, cond_destroy_bool, sens_destroy, cat_destroy,}; static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { struct filename_trans *ft = (struct filename_trans *)key; free(ft->name); free(key); free(datum); return 0; } static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { struct mls_range *rt = (struct mls_range *)datum; free(key); ebitmap_destroy(&rt->level[0].cat); ebitmap_destroy(&rt->level[1].cat); free(datum); return 0; } void ocontext_selinux_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; for (i = 0; i < OCON_NUM; i++) { c = ocontexts[i]; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); context_destroy(&ctmp->context[1]); if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF || i == OCON_FSUSE) free(ctmp->u.name); else if (i == OCON_IBENDPORT) free(ctmp->u.ibendport.dev_name); free(ctmp); } } } void ocontext_xen_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; for (i = 0; i < OCON_NUM; i++) { c = ocontexts[i]; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); context_destroy(&ctmp->context[1]); if (i == OCON_ISID || i == OCON_XEN_DEVICETREE) free(ctmp->u.name); free(ctmp); } } } /* * Free any memory allocated by a policy database structure. */ void policydb_destroy(policydb_t * p) { ocontext_t *c, *ctmp; genfs_t *g, *gtmp; unsigned int i; role_allow_t *ra, *lra = NULL; role_trans_t *tr, *ltr = NULL; if (!p) return; ebitmap_destroy(&p->policycaps); ebitmap_destroy(&p->permissive_map); symtabs_destroy(p->symtab); for (i = 0; i < SYM_NUM; i++) { if (p->sym_val_to_name[i]) free(p->sym_val_to_name[i]); } if (p->class_val_to_struct) free(p->class_val_to_struct); if (p->role_val_to_struct) free(p->role_val_to_struct); if (p->user_val_to_struct) free(p->user_val_to_struct); if (p->type_val_to_struct) free(p->type_val_to_struct); free(p->decl_val_to_struct); for (i = 0; i < SYM_NUM; i++) { (void)hashtab_map(p->scope[i].table, scope_destroy, 0); hashtab_destroy(p->scope[i].table); } avrule_block_list_destroy(p->global); free(p->name); free(p->version); avtab_destroy(&p->te_avtab); if (p->target_platform == SEPOL_TARGET_SELINUX) ocontext_selinux_free(p->ocontexts); else if (p->target_platform == SEPOL_TARGET_XEN) ocontext_xen_free(p->ocontexts); g = p->genfs; while (g) { free(g->fstype); c = g->head; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); free(ctmp->u.name); free(ctmp); } gtmp = g; g = g->next; free(gtmp); } cond_policydb_destroy(p); for (tr = p->role_tr; tr; tr = tr->next) { if (ltr) free(ltr); ltr = tr; } if (ltr) free(ltr); for (ra = p->role_allow; ra; ra = ra->next) { if (lra) free(lra); lra = ra; } if (lra) free(lra); hashtab_map(p->filename_trans, filenametr_destroy, NULL); hashtab_destroy(p->filename_trans); hashtab_map(p->range_tr, range_tr_destroy, NULL); hashtab_destroy(p->range_tr); if (p->type_attr_map) { for (i = 0; i < p->p_types.nprim; i++) { ebitmap_destroy(&p->type_attr_map[i]); } free(p->type_attr_map); } if (p->attr_type_map) { for (i = 0; i < p->p_types.nprim; i++) { ebitmap_destroy(&p->attr_type_map[i]); } free(p->attr_type_map); } return; } void symtabs_destroy(symtab_t * symtab) { int i; for (i = 0; i < SYM_NUM; i++) { (void)hashtab_map(symtab[i].table, destroy_f[i], 0); hashtab_destroy(symtab[i].table); } } int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { scope_datum_t *cur = (scope_datum_t *) datum; free(key); if (cur != NULL) { free(cur->decl_ids); } free(cur); return 0; } /* * Load the initial SIDs specified in a policy database * structure into a SID table. */ int policydb_load_isids(policydb_t * p, sidtab_t * s) { ocontext_t *head, *c; if (sepol_sidtab_init(s)) { ERR(NULL, "out of memory on SID table init"); return -1; } head = p->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { if (!c->context[0].user) { ERR(NULL, "SID %s was never defined", c->u.name); return -1; } if (sepol_sidtab_insert(s, c->sid[0], &c->context[0])) { ERR(NULL, "unable to load initial SID %s", c->u.name); return -1; } } return 0; } /* Declare a symbol for a certain avrule_block context. Insert it * into a symbol table for a policy. This function will handle * inserting the appropriate scope information in addition to * inserting the symbol into the hash table. * * arguments: * policydb_t *pol module policy to modify * uint32_t sym the symbole table for insertion (SYM_*) * hashtab_key_t key the key for the symbol - not cloned * hashtab_datum_t data the data for the symbol - not cloned * scope scope of this symbol, either SCOPE_REQ or SCOPE_DECL * avrule_decl_id identifier for this symbol's encapsulating declaration * value (out) assigned value to the symbol (if value is not NULL) * * returns: * 0 success * 1 success, but symbol already existed as a requirement * (datum was not inserted and needs to be free()d) * -1 general error * -2 scope conflicted * -ENOMEM memory error * error codes from hashtab_insert */ int symtab_insert(policydb_t * pol, uint32_t sym, hashtab_key_t key, hashtab_datum_t datum, uint32_t scope, uint32_t avrule_decl_id, uint32_t * value) { int rc, retval = 0; unsigned int i; scope_datum_t *scope_datum; /* check if the symbol is already there. multiple * declarations of non-roles/non-users are illegal, but * multiple requires are allowed. */ /* FIX ME - the failures after the hashtab_insert will leave * the policy in a inconsistent state. */ rc = hashtab_insert(pol->symtab[sym].table, key, datum); if (rc == SEPOL_OK) { /* if no value is passed in the symbol is not primary * (i.e. aliases) */ if (value) *value = ++pol->symtab[sym].nprim; } else if (rc == SEPOL_EEXIST) { retval = 1; /* symbol not added -- need to free() later */ } else { return rc; } /* get existing scope information; if there is not one then * create it */ scope_datum = (scope_datum_t *) hashtab_search(pol->scope[sym].table, key); if (scope_datum == NULL) { hashtab_key_t key2 = strdup((char *)key); if (!key2) return -ENOMEM; if ((scope_datum = malloc(sizeof(*scope_datum))) == NULL) { free(key2); return -ENOMEM; } scope_datum->scope = scope; scope_datum->decl_ids = NULL; scope_datum->decl_ids_len = 0; if ((rc = hashtab_insert(pol->scope[sym].table, key2, scope_datum)) != 0) { free(key2); free(scope_datum); return rc; } } else if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_DECL) { /* disallow multiple declarations for non-roles/users */ if (sym != SYM_ROLES && sym != SYM_USERS) { return -2; } /* Further confine that a role attribute can't have the same * name as another regular role, and a role attribute can't * be declared more than once. */ if (sym == SYM_ROLES) { role_datum_t *base_role; role_datum_t *cur_role = (role_datum_t *)datum; base_role = (role_datum_t *) hashtab_search(pol->symtab[sym].table, key); assert(base_role != NULL); if (!((base_role->flavor == ROLE_ROLE) && (cur_role->flavor == ROLE_ROLE))) { /* Only regular roles are allowed to have * multiple declarations. */ return -2; } } } else if (scope_datum->scope == SCOPE_REQ && scope == SCOPE_DECL) { scope_datum->scope = SCOPE_DECL; } /* search through the pre-existing list to avoid adding duplicates */ for (i = 0; i < scope_datum->decl_ids_len; i++) { if (scope_datum->decl_ids[i] == avrule_decl_id) { /* already there, so don't modify its scope */ return retval; } } if (add_i_to_a(avrule_decl_id, &scope_datum->decl_ids_len, &scope_datum->decl_ids) == -1) { return -ENOMEM; } if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_REQ) { /* Need to keep the decl at the end of the list */ uint32_t len, tmp; len = scope_datum->decl_ids_len; if (len < 2) { /* This should be impossible here */ return -1; } tmp = scope_datum->decl_ids[len-2]; scope_datum->decl_ids[len-2] = scope_datum->decl_ids[len-1]; scope_datum->decl_ids[len-1] = tmp; } return retval; } int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b) { type_set_init(dst); if (ebitmap_or(&dst->types, &a->types, &b->types)) { return -1; } if (ebitmap_or(&dst->negset, &a->negset, &b->negset)) { return -1; } dst->flags |= a->flags; dst->flags |= b->flags; return 0; } int type_set_cpy(type_set_t * dst, type_set_t * src) { type_set_init(dst); dst->flags = src->flags; if (ebitmap_cpy(&dst->types, &src->types)) return -1; if (ebitmap_cpy(&dst->negset, &src->negset)) return -1; return 0; } int type_set_or_eq(type_set_t * dst, type_set_t * other) { int ret; type_set_t tmp; if (type_set_or(&tmp, dst, other)) return -1; type_set_destroy(dst); ret = type_set_cpy(dst, &tmp); type_set_destroy(&tmp); return ret; } int role_set_get_role(role_set_t * x, uint32_t role) { if (x->flags & ROLE_STAR) return 1; if (ebitmap_get_bit(&x->roles, role - 1)) { if (x->flags & ROLE_COMP) return 0; else return 1; } else { if (x->flags & ROLE_COMP) return 1; else return 0; } } /***********************************************************************/ /* everything below is for policy reads */ /* The following are read functions for module structures */ static int role_set_read(role_set_t * r, struct policy_file *fp) { uint32_t buf[1]; int rc; if (ebitmap_read(&r->roles, fp)) return -1; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; r->flags = le32_to_cpu(buf[0]); return 0; } static int type_set_read(type_set_t * t, struct policy_file *fp) { uint32_t buf[1]; int rc; if (ebitmap_read(&t->types, fp)) return -1; if (ebitmap_read(&t->negset, fp)) return -1; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; t->flags = le32_to_cpu(buf[0]); return 0; } /* * Read a MLS range structure from a policydb binary * representation file. */ static int mls_read_range_helper(mls_range_t * r, struct policy_file *fp) { uint32_t buf[2], items; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto out; items = le32_to_cpu(buf[0]); if (items > ARRAY_SIZE(buf)) { ERR(fp->handle, "range overflow"); rc = -EINVAL; goto out; } rc = next_entry(buf, fp, sizeof(uint32_t) * items); if (rc < 0) { ERR(fp->handle, "truncated range"); goto out; } r->level[0].sens = le32_to_cpu(buf[0]); if (items > 1) r->level[1].sens = le32_to_cpu(buf[1]); else r->level[1].sens = r->level[0].sens; rc = ebitmap_read(&r->level[0].cat, fp); if (rc) { ERR(fp->handle, "error reading low categories"); goto out; } if (items > 1) { rc = ebitmap_read(&r->level[1].cat, fp); if (rc) { ERR(fp->handle, "error reading high categories"); goto bad_high; } } else { rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); if (rc) { ERR(fp->handle, "out of memory"); goto bad_high; } } rc = 0; out: return rc; bad_high: ebitmap_destroy(&r->level[0].cat); goto out; } /* * Read a semantic MLS level structure from a policydb binary * representation file. */ static int mls_read_semantic_level_helper(mls_semantic_level_t * l, struct policy_file *fp) { uint32_t buf[2], ncat; unsigned int i; mls_semantic_cat_t *cat; int rc; mls_semantic_level_init(l); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { ERR(fp->handle, "truncated level"); goto bad; } l->sens = le32_to_cpu(buf[0]); ncat = le32_to_cpu(buf[1]); for (i = 0; i < ncat; i++) { cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!cat) { ERR(fp->handle, "out of memory"); goto bad; } mls_semantic_cat_init(cat); cat->next = l->cat; l->cat = cat; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { ERR(fp->handle, "error reading level categories"); goto bad; } cat->low = le32_to_cpu(buf[0]); cat->high = le32_to_cpu(buf[1]); } return 0; bad: return -EINVAL; } /* * Read a semantic MLS range structure from a policydb binary * representation file. */ static int mls_read_semantic_range_helper(mls_semantic_range_t * r, struct policy_file *fp) { int rc; rc = mls_read_semantic_level_helper(&r->level[0], fp); if (rc) return rc; rc = mls_read_semantic_level_helper(&r->level[1], fp); return rc; } static int mls_level_to_semantic(mls_level_t * l, mls_semantic_level_t * sl) { unsigned int i; ebitmap_node_t *cnode; mls_semantic_cat_t *open_cat = NULL; mls_semantic_level_init(sl); sl->sens = l->sens; ebitmap_for_each_bit(&l->cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (open_cat) continue; open_cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!open_cat) return -1; mls_semantic_cat_init(open_cat); open_cat->low = i + 1; open_cat->next = sl->cat; sl->cat = open_cat; } else { if (!open_cat) continue; open_cat->high = i; open_cat = NULL; } } if (open_cat) open_cat->high = i; return 0; } static int mls_range_to_semantic(mls_range_t * r, mls_semantic_range_t * sr) { if (mls_level_to_semantic(&r->level[0], &sr->level[0])) return -1; if (mls_level_to_semantic(&r->level[1], &sr->level[1])) return -1; return 0; } /* * Read and validate a security context structure * from a policydb binary representation file. */ static int context_read_and_validate(context_struct_t * c, policydb_t * p, struct policy_file *fp) { uint32_t buf[3]; int rc; rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) { ERR(fp->handle, "context truncated"); return -1; } c->user = le32_to_cpu(buf[0]); c->role = le32_to_cpu(buf[1]); c->type = le32_to_cpu(buf[2]); if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) { if (mls_read_range_helper(&c->range, fp)) { ERR(fp->handle, "error reading MLS range " "of context"); return -1; } } if (!policydb_context_isvalid(p, c)) { ERR(fp->handle, "invalid security context"); context_destroy(c); return -1; } return 0; } /* * The following *_read functions are used to * read the symbol data from a policy database * binary representation file. */ static int perm_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp) { char *key = 0; perm_datum_t *perdatum; uint32_t buf[2]; size_t len; int rc; perdatum = calloc(1, sizeof(perm_datum_t)); if (!perdatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if(str_read(&key, fp, len)) goto bad; perdatum->s.value = le32_to_cpu(buf[1]); if (hashtab_insert(h, key, perdatum)) goto bad; return 0; bad: perm_destroy(key, perdatum, NULL); return -1; } static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; common_datum_t *comdatum; uint32_t buf[4]; size_t len, nel; unsigned int i; int rc; comdatum = calloc(1, sizeof(common_datum_t)); if (!comdatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; comdatum->s.value = le32_to_cpu(buf[1]); if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) goto bad; comdatum->permissions.nprim = le32_to_cpu(buf[2]); nel = le32_to_cpu(buf[3]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; for (i = 0; i < nel; i++) { if (perm_read(p, comdatum->permissions.table, fp)) goto bad; } if (hashtab_insert(h, key, comdatum)) goto bad; return 0; bad: common_destroy(key, comdatum, NULL); return -1; } static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, unsigned int ncons, int allowxtarget, struct policy_file *fp) { constraint_node_t *c, *lc; constraint_expr_t *e, *le; uint32_t buf[3]; size_t nexpr; unsigned int i, j; int rc, depth; lc = NULL; for (i = 0; i < ncons; i++) { c = calloc(1, sizeof(constraint_node_t)); if (!c) return -1; if (lc) lc->next = c; else *nodep = c; rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) return -1; c->permissions = le32_to_cpu(buf[0]); nexpr = le32_to_cpu(buf[1]); le = NULL; depth = -1; for (j = 0; j < nexpr; j++) { e = malloc(sizeof(constraint_expr_t)); if (!e) return -1; if (constraint_expr_init(e) == -1) { free(e); return -1; } if (le) { le->next = e; } else { c->expr = e; } rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); if (rc < 0) return -1; e->expr_type = le32_to_cpu(buf[0]); e->attr = le32_to_cpu(buf[1]); e->op = le32_to_cpu(buf[2]); switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) return -1; break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) return -1; depth--; break; case CEXPR_ATTR: if (depth == (CEXPR_MAXDEPTH - 1)) return -1; depth++; break; case CEXPR_NAMES: if (!allowxtarget && (e->attr & CEXPR_XTARGET)) return -1; if (depth == (CEXPR_MAXDEPTH - 1)) return -1; depth++; if (ebitmap_read(&e->names, fp)) return -1; if (p->policy_type != POLICY_KERN && type_set_read(e->type_names, fp)) return -1; else if (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && type_set_read(e->type_names, fp)) return -1; break; default: return -1; } le = e; } if (depth != 0) return -1; lc = c; } return 0; } static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; class_datum_t *cladatum; uint32_t buf[6]; size_t len, len2, ncons, nel; unsigned int i; int rc; cladatum = (class_datum_t *) calloc(1, sizeof(class_datum_t)); if (!cladatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 6); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; len2 = le32_to_cpu(buf[1]); if (is_saturated(len2)) goto bad; cladatum->s.value = le32_to_cpu(buf[2]); if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) goto bad; cladatum->permissions.nprim = le32_to_cpu(buf[3]); nel = le32_to_cpu(buf[4]); ncons = le32_to_cpu(buf[5]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; if (len2) { cladatum->comkey = malloc(len2 + 1); if (!cladatum->comkey) goto bad; rc = next_entry(cladatum->comkey, fp, len2); if (rc < 0) goto bad; cladatum->comkey[len2] = 0; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); if (!cladatum->comdatum) { ERR(fp->handle, "unknown common %s", cladatum->comkey); goto bad; } } for (i = 0; i < nel; i++) { if (perm_read(p, cladatum->permissions.table, fp)) goto bad; } if (read_cons_helper(p, &cladatum->constraints, ncons, 0, fp)) goto bad; if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { /* grab the validatetrans rules */ rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; ncons = le32_to_cpu(buf[0]); if (read_cons_helper(p, &cladatum->validatetrans, ncons, 1, fp)) goto bad; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto bad; cladatum->default_user = le32_to_cpu(buf[0]); cladatum->default_role = le32_to_cpu(buf[1]); cladatum->default_range = le32_to_cpu(buf[2]); } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; cladatum->default_type = le32_to_cpu(buf[0]); } if (hashtab_insert(h, key, cladatum)) goto bad; return 0; bad: class_destroy(key, cladatum, NULL); return -1; } static int role_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; role_datum_t *role; uint32_t buf[3]; size_t len; int rc, to_read = 2; role = calloc(1, sizeof(role_datum_t)); if (!role) return -1; if (policydb_has_boundary_feature(p)) to_read = 3; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; role->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) role->bounds = le32_to_cpu(buf[2]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; if (ebitmap_read(&role->dominates, fp)) goto bad; if (p->policy_type == POLICY_KERN) { if (ebitmap_read(&role->types.types, fp)) goto bad; } else { if (type_set_read(&role->types, fp)) goto bad; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; role->flavor = le32_to_cpu(buf[0]); if (ebitmap_read(&role->roles, fp)) goto bad; } if (strcmp(key, OBJECT_R) == 0) { if (role->s.value != OBJECT_R_VAL) { ERR(fp->handle, "role %s has wrong value %d", OBJECT_R, role->s.value); role_destroy(key, role, NULL); return -1; } role_destroy(key, role, NULL); return 0; } if (hashtab_insert(h, key, role)) goto bad; return 0; bad: role_destroy(key, role, NULL); return -1; } static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; type_datum_t *typdatum; uint32_t buf[5]; size_t len; int rc, to_read; int pos = 0; typdatum = calloc(1, sizeof(type_datum_t)); if (!typdatum) return -1; if (policydb_has_boundary_feature(p)) { if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) to_read = 5; else to_read = 4; } else if (p->policy_type == POLICY_KERN) to_read = 3; else if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) to_read = 5; else to_read = 4; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[pos]); if (zero_or_saturated(len)) goto bad; typdatum->s.value = le32_to_cpu(buf[++pos]); if (policydb_has_boundary_feature(p)) { uint32_t properties; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { typdatum->primary = le32_to_cpu(buf[++pos]); properties = le32_to_cpu(buf[++pos]); } else { properties = le32_to_cpu(buf[++pos]); if (properties & TYPEDATUM_PROPERTY_PRIMARY) typdatum->primary = 1; } if (properties & TYPEDATUM_PROPERTY_ATTRIBUTE) typdatum->flavor = TYPE_ATTRIB; if (properties & TYPEDATUM_PROPERTY_ALIAS && p->policy_type != POLICY_KERN) typdatum->flavor = TYPE_ALIAS; if (properties & TYPEDATUM_PROPERTY_PERMISSIVE && p->policy_type != POLICY_KERN) typdatum->flags |= TYPE_FLAGS_PERMISSIVE; typdatum->bounds = le32_to_cpu(buf[++pos]); } else { typdatum->primary = le32_to_cpu(buf[++pos]); if (p->policy_type != POLICY_KERN) { typdatum->flavor = le32_to_cpu(buf[++pos]); if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) typdatum->flags = le32_to_cpu(buf[++pos]); } } if (p->policy_type != POLICY_KERN) { if (ebitmap_read(&typdatum->types, fp)) goto bad; } key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; if (hashtab_insert(h, key, typdatum)) goto bad; return 0; bad: type_destroy(key, typdatum, NULL); return -1; } int role_trans_read(policydb_t *p, struct policy_file *fp) { role_trans_t **t = &p->role_tr; unsigned int i; uint32_t buf[3], nel; role_trans_t *tr, *ltr; int rc; int new_roletr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_ROLETRANS); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { tr = calloc(1, sizeof(struct role_trans)); if (!tr) { return -1; } if (ltr) { ltr->next = tr; } else { *t = tr; } rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) return -1; tr->role = le32_to_cpu(buf[0]); tr->type = le32_to_cpu(buf[1]); tr->new_role = le32_to_cpu(buf[2]); if (new_roletr) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; tr->tclass = le32_to_cpu(buf[0]); } else tr->tclass = SECCLASS_PROCESS; ltr = tr; } return 0; } int role_allow_read(role_allow_t ** r, struct policy_file *fp) { unsigned int i; uint32_t buf[2], nel; role_allow_t *ra, *lra; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { ra = calloc(1, sizeof(struct role_allow)); if (!ra) { return -1; } if (lra) { lra->next = ra; } else { *r = ra; } rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; ra->role = le32_to_cpu(buf[0]); ra->new_role = le32_to_cpu(buf[1]); lra = ra; } return 0; } int filename_trans_read(policydb_t *p, struct policy_file *fp) { unsigned int i; uint32_t buf[4], nel, len; filename_trans_t *ft; filename_trans_datum_t *otype; int rc; char *name; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); for (i = 0; i < nel; i++) { ft = NULL; otype = NULL; name = NULL; ft = calloc(1, sizeof(*ft)); if (!ft) goto err; otype = calloc(1, sizeof(*otype)); if (!otype) goto err; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto err; name = calloc(len + 1, sizeof(*name)); if (!name) goto err; ft->name = name; rc = next_entry(name, fp, len); if (rc < 0) goto err; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) goto err; ft->stype = le32_to_cpu(buf[0]); ft->ttype = le32_to_cpu(buf[1]); ft->tclass = le32_to_cpu(buf[2]); otype->otype = le32_to_cpu(buf[3]); rc = hashtab_insert(p->filename_trans, (hashtab_key_t) ft, otype); if (rc) { if (rc != SEPOL_EEXIST) goto err; /* * Some old policies were wrongly generated with * duplicate filename transition rules. For backward * compatibility, do not reject such policies, just * issue a warning and ignore the duplicate. */ WARN(fp->handle, "Duplicate name-based type_transition %s %s:%s \"%s\": %s, ignoring", p->p_type_val_to_name[ft->stype - 1], p->p_type_val_to_name[ft->ttype - 1], p->p_class_val_to_name[ft->tclass - 1], ft->name, p->p_type_val_to_name[otype->otype - 1]); free(ft); free(name); free(otype); /* continue, ignoring this one */ } } return 0; err: free(ft); free(otype); free(name); return -1; } static int ocontext_read_xen(struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, len; ocontext_t *l, *c; uint32_t buf[8]; int rc; for (i = 0; i < info->ocon_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { c = calloc(1, sizeof(ocontext_t)); if (!c) return -1; if (l) l->next = c; else p->ocontexts[i] = c; l = c; switch (i) { case OCON_XEN_ISID: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->sid[0] = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_PIRQ: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->u.pirq = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_IOPORT: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.ioport.low_ioport = le32_to_cpu(buf[0]); c->u.ioport.high_ioport = le32_to_cpu(buf[1]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_IOMEM: if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { uint64_t b64[2]; rc = next_entry(b64, fp, sizeof(uint64_t) * 2); if (rc < 0) return -1; c->u.iomem.low_iomem = le64_to_cpu(b64[0]); c->u.iomem.high_iomem = le64_to_cpu(b64[1]); } else { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.iomem.low_iomem = le32_to_cpu(buf[0]); c->u.iomem.high_iomem = le32_to_cpu(buf[1]); } if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_PCIDEVICE: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->u.device = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_DEVICETREE: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) return -1; c->u.name = malloc(len + 1); if (!c->u.name) return -1; rc = next_entry(c->u.name, fp, len); if (rc < 0) return -1; c->u.name[len] = 0; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; default: /* should never get here */ ERR(fp->handle, "Unknown Xen ocontext"); return -1; } } } return 0; } static int ocontext_read_selinux(struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { unsigned int i, j; size_t nel, len; ocontext_t *l, *c; uint32_t buf[8]; int rc; for (i = 0; i < info->ocon_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { c = calloc(1, sizeof(ocontext_t)); if (!c) { return -1; } if (l) { l->next = c; } else { p->ocontexts[i] = c; } l = c; switch (i) { case OCON_ISID: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->sid[0] = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_FS: case OCON_NETIF: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len) || len > 63) return -1; c->u.name = malloc(len + 1); if (!c->u.name) return -1; rc = next_entry(c->u.name, fp, len); if (rc < 0) return -1; c->u.name[len] = 0; if (context_read_and_validate (&c->context[0], p, fp)) return -1; if (context_read_and_validate (&c->context[1], p, fp)) return -1; break; case OCON_IBPKEY: { uint32_t pkey_lo, pkey_hi; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) return -1; pkey_lo = le32_to_cpu(buf[2]); pkey_hi = le32_to_cpu(buf[3]); if (pkey_lo > UINT16_MAX || pkey_hi > UINT16_MAX) return -1; c->u.ibpkey.low_pkey = pkey_lo; c->u.ibpkey.high_pkey = pkey_hi; /* we want c->u.ibpkey.subnet_prefix in network * (big-endian) order, just memcpy it */ memcpy(&c->u.ibpkey.subnet_prefix, buf, sizeof(c->u.ibpkey.subnet_prefix)); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } case OCON_IBENDPORT: { uint32_t port; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (len == 0 || len > IB_DEVICE_NAME_MAX - 1) return -1; port = le32_to_cpu(buf[1]); if (port > UINT8_MAX || port == 0) return -1; c->u.ibendport.dev_name = malloc(len + 1); if (!c->u.ibendport.dev_name) return -1; rc = next_entry(c->u.ibendport.dev_name, fp, len); if (rc < 0) return -1; c->u.ibendport.dev_name[len] = 0; c->u.ibendport.port = port; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } case OCON_PORT: rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) return -1; c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.low_port = le32_to_cpu(buf[1]); c->u.port.high_port = le32_to_cpu(buf[2]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_NODE: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.node.addr = buf[0]; /* network order */ c->u.node.mask = buf[1]; /* network order */ if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_FSUSE: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->v.behavior = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[1]); if (zero_or_saturated(len)) return -1; c->u.name = malloc(len + 1); if (!c->u.name) return -1; rc = next_entry(c->u.name, fp, len); if (rc < 0) return -1; c->u.name[len] = 0; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_NODE6:{ int k; rc = next_entry(buf, fp, sizeof(uint32_t) * 8); if (rc < 0) return -1; for (k = 0; k < 4; k++) /* network order */ c->u.node6.addr[k] = buf[k]; for (k = 0; k < 4; k++) /* network order */ c->u.node6.mask[k] = buf[k + 4]; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } default:{ ERR(fp->handle, "Unknown SELinux ocontext"); return -1; } } } } return 0; } static int ocontext_read(struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { int rc = -1; switch (p->target_platform) { case SEPOL_TARGET_SELINUX: rc = ocontext_read_selinux(info, p, fp); break; case SEPOL_TARGET_XEN: rc = ocontext_read_xen(info, p, fp); break; default: ERR(fp->handle, "Unknown target"); } return rc; } static int genfs_read(policydb_t * p, struct policy_file *fp) { uint32_t buf[1]; size_t nel, nel2, len, len2; genfs_t *genfs_p, *newgenfs, *genfs; size_t i, j; ocontext_t *l, *c, *newc = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; nel = le32_to_cpu(buf[0]); genfs_p = NULL; for (i = 0; i < nel; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; newgenfs = calloc(1, sizeof(genfs_t)); if (!newgenfs) goto bad; newgenfs->fstype = malloc(len + 1); if (!newgenfs->fstype) { free(newgenfs); goto bad; } rc = next_entry(newgenfs->fstype, fp, len); if (rc < 0) { free(newgenfs->fstype); free(newgenfs); goto bad; } newgenfs->fstype[len] = 0; for (genfs_p = NULL, genfs = p->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { ERR(fp->handle, "dup genfs fstype %s", newgenfs->fstype); free(newgenfs->fstype); free(newgenfs); goto bad; } if (strcmp(newgenfs->fstype, genfs->fstype) < 0) break; } newgenfs->next = genfs; if (genfs_p) genfs_p->next = newgenfs; else p->genfs = newgenfs; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { newc = calloc(1, sizeof(ocontext_t)); if (!newc) { goto bad; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; newc->u.name = malloc(len + 1); if (!newc->u.name) { goto bad; } rc = next_entry(newc->u.name, fp, len); if (rc < 0) goto bad; newc->u.name[len] = 0; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; newc->v.sclass = le32_to_cpu(buf[0]); if (context_read_and_validate(&newc->context[0], p, fp)) goto bad; for (l = NULL, c = newgenfs->head; c; l = c, c = c->next) { if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || newc->v.sclass == c->v.sclass)) { ERR(fp->handle, "dup genfs entry " "(%s,%s)", newgenfs->fstype, c->u.name); goto bad; } len = strlen(newc->u.name); len2 = strlen(c->u.name); if (len > len2) break; } newc->next = c; if (l) l->next = newc; else newgenfs->head = newc; /* clear newc after a new owner has the pointer */ newc = NULL; } } return 0; bad: if (newc) { context_destroy(&newc->context[0]); context_destroy(&newc->context[1]); free(newc->u.name); free(newc); } return -1; } /* * Read a MLS level structure from a policydb binary * representation file. */ static int mls_read_level(mls_level_t * lp, struct policy_file *fp) { uint32_t buf[1]; int rc; mls_level_init(lp); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated level"); goto bad; } lp->sens = le32_to_cpu(buf[0]); if (ebitmap_read(&lp->cat, fp)) { ERR(fp->handle, "error reading level categories"); goto bad; } return 0; bad: return -EINVAL; } static int user_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; user_datum_t *usrdatum; uint32_t buf[3]; size_t len; int rc, to_read = 2; usrdatum = calloc(1, sizeof(user_datum_t)); if (!usrdatum) return -1; if (policydb_has_boundary_feature(p)) to_read = 3; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; usrdatum->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) usrdatum->bounds = le32_to_cpu(buf[2]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; if (p->policy_type == POLICY_KERN) { if (ebitmap_read(&usrdatum->roles.roles, fp)) goto bad; } else { if (role_set_read(&usrdatum->roles, fp)) goto bad; } /* users were not allowed in mls modules before version * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been * required - the mls fields will be empty. user declarations in * non-mls modules will also have empty mls fields */ if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_MOD && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) { if (mls_read_range_helper(&usrdatum->exp_range, fp)) goto bad; if (mls_read_level(&usrdatum->exp_dfltlevel, fp)) goto bad; if (p->policy_type != POLICY_KERN) { if (mls_range_to_semantic(&usrdatum->exp_range, &usrdatum->range)) goto bad; if (mls_level_to_semantic(&usrdatum->exp_dfltlevel, &usrdatum->dfltlevel)) goto bad; } } else if ((p->policy_type == POLICY_MOD && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) { if (mls_read_semantic_range_helper(&usrdatum->range, fp)) goto bad; if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp)) goto bad; } if (hashtab_insert(h, key, usrdatum)) goto bad; return 0; bad: user_destroy(key, usrdatum, NULL); return -1; } static int sens_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp) { char *key = 0; level_datum_t *levdatum; uint32_t buf[2], len; int rc; levdatum = malloc(sizeof(level_datum_t)); if (!levdatum) return -1; level_datum_init(levdatum); rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; levdatum->isalias = le32_to_cpu(buf[1]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; levdatum->level = malloc(sizeof(mls_level_t)); if (!levdatum->level || mls_read_level(levdatum->level, fp)) goto bad; if (hashtab_insert(h, key, levdatum)) goto bad; return 0; bad: sens_destroy(key, levdatum, NULL); return -1; } static int cat_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp) { char *key = 0; cat_datum_t *catdatum; uint32_t buf[3], len; int rc; catdatum = malloc(sizeof(cat_datum_t)); if (!catdatum) return -1; cat_datum_init(catdatum); rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if(zero_or_saturated(len)) goto bad; catdatum->s.value = le32_to_cpu(buf[1]); catdatum->isalias = le32_to_cpu(buf[2]); key = malloc(len + 1); if (!key) goto bad; rc = next_entry(key, fp, len); if (rc < 0) goto bad; key[len] = 0; if (hashtab_insert(h, key, catdatum)) goto bad; return 0; bad: cat_destroy(key, catdatum, NULL); return -1; } static int (*read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, struct policy_file * fp) = { common_read, class_read, role_read, type_read, user_read, cond_read_bool, sens_read, cat_read,}; /************** module reading functions below **************/ static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) { unsigned int i; uint32_t buf[2], len; class_perm_node_t *cur, *tail = NULL; avrule_t *avrule; int rc; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) return NULL; avrule_init(avrule); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; avrule->specified = le32_to_cpu(buf[0]); avrule->flags = le32_to_cpu(buf[1]); if (type_set_read(&avrule->stypes, fp)) goto bad; if (type_set_read(&avrule->ttypes, fp)) goto bad; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { cur = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!cur) goto bad; class_perm_node_init(cur); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { free(cur); goto bad; } cur->tclass = le32_to_cpu(buf[0]); cur->data = le32_to_cpu(buf[1]); if (!tail) { avrule->perms = cur; } else { tail->next = cur; } tail = cur; } if (avrule->specified & AVRULE_XPERMS) { uint8_t buf8; size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ERR(fp->handle, "module policy version %u does not support ioctl" " extended permissions rules and one was specified", p->policyvers); goto bad; } if (p->target_platform != SEPOL_TARGET_SELINUX) { ERR(fp->handle, "Target platform %s does not support ioctl" " extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); goto bad; } avrule->xperms = calloc(1, sizeof(*avrule->xperms)); if (!avrule->xperms) goto bad; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } avrule->xperms->specified = buf8; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } avrule->xperms->driver = buf8; rc = next_entry(buf32, fp, sizeof(uint32_t)*nel); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } for (i = 0; i < nel; i++) avrule->xperms->perms[i] = le32_to_cpu(buf32[i]); } return avrule; bad: if (avrule) { avrule_destroy(avrule); free(avrule); } return NULL; } static int range_read(policydb_t * p, struct policy_file *fp) { uint32_t buf[2], nel; range_trans_t *rt = NULL; struct mls_range *r = NULL; range_trans_rule_t *rtr = NULL, *lrtr = NULL; unsigned int i; int new_rangetr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_RANGETRANS); int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); for (i = 0; i < nel; i++) { rt = calloc(1, sizeof(range_trans_t)); if (!rt) return -1; rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) goto err; rt->source_type = le32_to_cpu(buf[0]); rt->target_type = le32_to_cpu(buf[1]); if (new_rangetr) { rc = next_entry(buf, fp, (sizeof(uint32_t))); if (rc < 0) goto err; rt->target_class = le32_to_cpu(buf[0]); } else rt->target_class = SECCLASS_PROCESS; r = calloc(1, sizeof(*r)); if (!r) goto err; if (mls_read_range_helper(r, fp)) goto err; if (p->policy_type == POLICY_KERN) { rc = hashtab_insert(p->range_tr, (hashtab_key_t)rt, r); if (rc) goto err; rt = NULL; r = NULL; continue; } /* Module policy: convert to range_trans_rule and discard. */ rtr = malloc(sizeof(range_trans_rule_t)); if (!rtr) goto err; range_trans_rule_init(rtr); if (ebitmap_set_bit(&rtr->stypes.types, rt->source_type - 1, 1)) goto err; if (ebitmap_set_bit(&rtr->ttypes.types, rt->target_type - 1, 1)) goto err; if (ebitmap_set_bit(&rtr->tclasses, rt->target_class - 1, 1)) goto err; if (mls_range_to_semantic(r, &rtr->trange)) goto err; if (lrtr) lrtr->next = rtr; else p->global->enabled->range_tr_rules = rtr; free(rt); rt = NULL; free(r); r = NULL; lrtr = rtr; } return 0; err: free(rt); if (r) { mls_range_destroy(r); free(r); } if (rtr) { range_trans_rule_destroy(rtr); free(rtr); } return -1; } int avrule_read_list(policydb_t * p, avrule_t ** avrules, struct policy_file *fp) { unsigned int i; avrule_t *cur, *tail; uint32_t buf[1], len; int rc; *avrules = tail = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { return -1; } len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { cur = avrule_read(p, fp); if (!cur) { return -1; } if (!tail) { *avrules = cur; } else { tail->next = cur; } tail = cur; } return 0; } static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r, struct policy_file *fp) { uint32_t buf[1], nel; unsigned int i; role_trans_rule_t *tr, *ltr; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { tr = malloc(sizeof(role_trans_rule_t)); if (!tr) { return -1; } role_trans_rule_init(tr); if (ltr) { ltr->next = tr; } else { *r = tr; } if (role_set_read(&tr->roles, fp)) return -1; if (type_set_read(&tr->types, fp)) return -1; if (p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS) { if (ebitmap_read(&tr->classes, fp)) return -1; } else { if (ebitmap_set_bit(&tr->classes, SECCLASS_PROCESS - 1, 1)) return -1; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; tr->new_role = le32_to_cpu(buf[0]); ltr = tr; } return 0; } static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp) { unsigned int i; uint32_t buf[1], nel; role_allow_rule_t *ra, *lra; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { ra = malloc(sizeof(role_allow_rule_t)); if (!ra) { return -1; } role_allow_rule_init(ra); if (lra) { lra->next = ra; } else { *r = ra; } if (role_set_read(&ra->roles, fp)) return -1; if (role_set_read(&ra->new_roles, fp)) return -1; lra = ra; } return 0; } static int filename_trans_rule_read(filename_trans_rule_t ** r, struct policy_file *fp) { uint32_t buf[2], nel; unsigned int i, len; filename_trans_rule_t *ftr, *lftr; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lftr = NULL; for (i = 0; i < nel; i++) { ftr = malloc(sizeof(*ftr)); if (!ftr) return -1; filename_trans_rule_init(ftr); if (lftr) lftr->next = ftr; else *r = ftr; lftr = ftr; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) return -1; ftr->name = malloc(len + 1); if (!ftr->name) return -1; rc = next_entry(ftr->name, fp, len); if (rc) return -1; ftr->name[len] = 0; if (type_set_read(&ftr->stypes, fp)) return -1; if (type_set_read(&ftr->ttypes, fp)) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; ftr->tclass = le32_to_cpu(buf[0]); ftr->otype = le32_to_cpu(buf[1]); } return 0; } static int range_trans_rule_read(range_trans_rule_t ** r, struct policy_file *fp) { uint32_t buf[1], nel; unsigned int i; range_trans_rule_t *rt, *lrt = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); for (i = 0; i < nel; i++) { rt = malloc(sizeof(range_trans_rule_t)); if (!rt) { return -1; } range_trans_rule_init(rt); if (lrt) lrt->next = rt; else *r = rt; if (type_set_read(&rt->stypes, fp)) return -1; if (type_set_read(&rt->ttypes, fp)) return -1; if (ebitmap_read(&rt->tclasses, fp)) return -1; if (mls_read_semantic_range_helper(&rt->trange, fp)) return -1; lrt = rt; } return 0; } static int scope_index_read(scope_index_t * scope_index, unsigned int num_scope_syms, struct policy_file *fp) { unsigned int i; uint32_t buf[1]; int rc; for (i = 0; i < num_scope_syms; i++) { if (ebitmap_read(scope_index->scope + i, fp) < 0) { return -1; } } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; scope_index->class_perms_len = le32_to_cpu(buf[0]); if (scope_index->class_perms_len == 0) { scope_index->class_perms_map = NULL; return 0; } if ((scope_index->class_perms_map = calloc(scope_index->class_perms_len, sizeof(*scope_index->class_perms_map))) == NULL) { return -1; } for (i = 0; i < scope_index->class_perms_len; i++) { if (ebitmap_read(scope_index->class_perms_map + i, fp) < 0) { return -1; } } return 0; } static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl, unsigned int num_scope_syms, struct policy_file *fp) { uint32_t buf[2], nprim, nel; unsigned int i, j; int rc; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; decl->decl_id = le32_to_cpu(buf[0]); decl->enabled = le32_to_cpu(buf[1]); if (cond_read_list(p, &decl->cond_list, fp) == -1 || avrule_read_list(p, &decl->avrules, fp) == -1 || role_trans_rule_read(p, &decl->role_tr_rules, fp) == -1 || role_allow_rule_read(&decl->role_allow_rules, fp) == -1) { return -1; } if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && filename_trans_rule_read(&decl->filename_trans_rules, fp)) return -1; if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && range_trans_rule_read(&decl->range_tr_rules, fp) == -1) { return -1; } if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 || scope_index_read(&decl->declared, num_scope_syms, fp) == -1) { return -1; } for (i = 0; i < num_scope_syms; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; nprim = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[1]); for (j = 0; j < nel; j++) { if (read_f[i] (p, decl->symtab[i].table, fp)) { return -1; } } decl->symtab[i].nprim = nprim; } return 0; } static int avrule_block_read(policydb_t * p, avrule_block_t ** block, unsigned int num_scope_syms, struct policy_file *fp) { avrule_block_t *last_block = NULL, *curblock; uint32_t buf[1], num_blocks, nel; int rc; assert(*block == NULL); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; num_blocks = le32_to_cpu(buf[0]); nel = num_blocks; while (num_blocks > 0) { avrule_decl_t *last_decl = NULL, *curdecl; uint32_t num_decls; if ((curblock = calloc(1, sizeof(*curblock))) == NULL) { return -1; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { free(curblock); return -1; } /* if this is the first block its non-optional, else its optional */ if (num_blocks != nel) curblock->flags |= AVRULE_OPTIONAL; num_decls = le32_to_cpu(buf[0]); while (num_decls > 0) { if ((curdecl = avrule_decl_create(0)) == NULL) { avrule_block_destroy(curblock); return -1; } if (avrule_decl_read(p, curdecl, num_scope_syms, fp) == -1) { avrule_decl_destroy(curdecl); avrule_block_destroy(curblock); return -1; } if (curdecl->enabled) { if (curblock->enabled != NULL) { /* probably a corrupt file */ avrule_decl_destroy(curdecl); avrule_block_destroy(curblock); return -1; } curblock->enabled = curdecl; } /* one must be careful to reconstruct the * decl chain in its correct order */ if (curblock->branch_list == NULL) { curblock->branch_list = curdecl; } else { assert(last_decl); last_decl->next = curdecl; } last_decl = curdecl; num_decls--; } if (*block == NULL) { *block = curblock; } else { assert(last_block); last_block->next = curblock; } last_block = curblock; num_blocks--; } return 0; } static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) { scope_datum_t *scope = NULL; uint32_t buf[2]; char *key = NULL; size_t key_len; unsigned int i; hashtab_t h = p->scope[symnum].table; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto cleanup; key_len = le32_to_cpu(buf[0]); if (zero_or_saturated(key_len)) goto cleanup; key = malloc(key_len + 1); if (!key) goto cleanup; rc = next_entry(key, fp, key_len); if (rc < 0) goto cleanup; key[key_len] = '\0'; /* ensure that there already exists a symbol with this key */ if (hashtab_search(p->symtab[symnum].table, key) == NULL) { goto cleanup; } if ((scope = calloc(1, sizeof(*scope))) == NULL) { goto cleanup; } rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto cleanup; scope->scope = le32_to_cpu(buf[0]); scope->decl_ids_len = le32_to_cpu(buf[1]); if (scope->decl_ids_len == 0) { ERR(fp->handle, "invalid scope with no declaration"); goto cleanup; } if ((scope->decl_ids = malloc(scope->decl_ids_len * sizeof(uint32_t))) == NULL) { goto cleanup; } rc = next_entry(scope->decl_ids, fp, sizeof(uint32_t) * scope->decl_ids_len); if (rc < 0) goto cleanup; for (i = 0; i < scope->decl_ids_len; i++) { scope->decl_ids[i] = le32_to_cpu(scope->decl_ids[i]); } if (strcmp(key, "object_r") == 0 && h == p->p_roles_scope.table) { /* object_r was already added to this table in roles_init() */ scope_destroy(key, scope, NULL); } else { if (hashtab_insert(h, key, scope)) { goto cleanup; } } return 0; cleanup: scope_destroy(key, scope, NULL); return -1; } /* * Read the configuration data from a policy database binary * representation file into a policy database structure. */ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) { unsigned int i, j, r_policyvers; uint32_t buf[5]; size_t len, nprim, nel; char *policydb_str; struct policydb_compat_info *info; unsigned int policy_type, bufindex; ebitmap_node_t *tnode; int rc; /* Read the magic number and string length. */ rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return POLICYDB_ERROR; for (i = 0; i < 2; i++) buf[i] = le32_to_cpu(buf[i]); if (buf[0] == POLICYDB_MAGIC) { policy_type = POLICY_KERN; } else if (buf[0] == POLICYDB_MOD_MAGIC) { policy_type = POLICY_MOD; } else { ERR(fp->handle, "policydb magic number %#08x does not " "match expected magic number %#08x or %#08x", buf[0], POLICYDB_MAGIC, POLICYDB_MOD_MAGIC); return POLICYDB_ERROR; } len = buf[1]; if (len == 0 || len > POLICYDB_STRING_MAX_LENGTH) { ERR(fp->handle, "policydb string length %s ", len ? "too long" : "zero"); return POLICYDB_ERROR; } policydb_str = malloc(len + 1); if (!policydb_str) { ERR(fp->handle, "unable to allocate memory for policydb " "string of length %zu", len); return POLICYDB_ERROR; } rc = next_entry(policydb_str, fp, len); if (rc < 0) { ERR(fp->handle, "truncated policydb string identifier"); free(policydb_str); return POLICYDB_ERROR; } policydb_str[len] = 0; if (policy_type == POLICY_KERN) { for (i = 0; i < POLICYDB_TARGET_SZ; i++) { if ((strcmp(policydb_str, policydb_target_strings[i]) == 0)) { policydb_set_target_platform(p, i); break; } } if (i == POLICYDB_TARGET_SZ) { ERR(fp->handle, "cannot find a valid target for policy " "string %s", policydb_str); free(policydb_str); return POLICYDB_ERROR; } } else { if (strcmp(policydb_str, POLICYDB_MOD_STRING)) { ERR(fp->handle, "invalid string identifier %s", policydb_str); free(policydb_str); return POLICYDB_ERROR; } } /* Done with policydb_str. */ free(policydb_str); policydb_str = NULL; /* Read the version, config, and table sizes (and policy type if it's a module). */ if (policy_type == POLICY_KERN) nel = 4; else nel = 5; rc = next_entry(buf, fp, sizeof(uint32_t) * nel); if (rc < 0) return POLICYDB_ERROR; for (i = 0; i < nel; i++) buf[i] = le32_to_cpu(buf[i]); bufindex = 0; if (policy_type == POLICY_MOD) { /* We know it's a module but not whether it's a base module or regular binary policy module. buf[0] tells us which. */ policy_type = buf[bufindex]; if (policy_type != POLICY_MOD && policy_type != POLICY_BASE) { ERR(fp->handle, "unknown module type: %#08x", policy_type); return POLICYDB_ERROR; } bufindex++; } r_policyvers = buf[bufindex]; if (policy_type == POLICY_KERN) { if (r_policyvers < POLICYDB_VERSION_MIN || r_policyvers > POLICYDB_VERSION_MAX) { ERR(fp->handle, "policydb version %d does not match " "my version range %d-%d", buf[bufindex], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); return POLICYDB_ERROR; } } else if (policy_type == POLICY_BASE || policy_type == POLICY_MOD) { if (r_policyvers < MOD_POLICYDB_VERSION_MIN || r_policyvers > MOD_POLICYDB_VERSION_MAX) { ERR(fp->handle, "policydb module version %d does " "not match my version range %d-%d", buf[bufindex], MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); return POLICYDB_ERROR; } } else { assert(0); } bufindex++; /* Set the policy type and version from the read values. */ p->policy_type = policy_type; p->policyvers = r_policyvers; if (buf[bufindex] & POLICYDB_CONFIG_MLS) { p->mls = 1; } else { p->mls = 0; } p->handle_unknown = buf[bufindex] & POLICYDB_CONFIG_UNKNOWN_MASK; bufindex++; info = policydb_lookup_compat(r_policyvers, policy_type, p->target_platform); if (!info) { ERR(fp->handle, "unable to find policy compat info " "for version %d", r_policyvers); goto bad; } if (buf[bufindex] != info->sym_num || buf[bufindex + 1] != info->ocon_num) { ERR(fp->handle, "policydb table sizes (%d,%d) do not " "match mine (%d,%d)", buf[bufindex], buf[bufindex + 1], info->sym_num, info->ocon_num); goto bad; } if (p->policy_type == POLICY_MOD) { /* Get the module name and version */ if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; if ((p->name = malloc(len + 1)) == NULL) { goto bad; } if ((rc = next_entry(p->name, fp, len)) < 0) { goto bad; } p->name[len] = '\0'; if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } len = le32_to_cpu(buf[0]); if (zero_or_saturated(len)) goto bad; if ((p->version = malloc(len + 1)) == NULL) { goto bad; } if ((rc = next_entry(p->version, fp, len)) < 0) { goto bad; } p->version[len] = '\0'; } if ((p->policyvers >= POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_BASE) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_MOD)) { if (ebitmap_read(&p->policycaps, fp)) goto bad; } if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { if (ebitmap_read(&p->permissive_map, fp)) goto bad; } for (i = 0; i < info->sym_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; nprim = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[1]); if (nel && !nprim) { ERR(fp->handle, "unexpected items in symbol table with no symbol"); goto bad; } for (j = 0; j < nel; j++) { if (read_f[i] (p, p->symtab[i].table, fp)) goto bad; } p->symtab[i].nprim = nprim; } if (policy_type == POLICY_KERN) { if (avtab_read(&p->te_avtab, fp, r_policyvers)) goto bad; if (r_policyvers >= POLICYDB_VERSION_BOOL) if (cond_read_list(p, &p->cond_list, fp)) goto bad; if (role_trans_read(p, fp)) goto bad; if (role_allow_read(&p->role_allow, fp)) goto bad; if (r_policyvers >= POLICYDB_VERSION_FILENAME_TRANS && filename_trans_read(p, fp)) goto bad; } else { /* first read the AV rule blocks, then the scope tables */ avrule_block_destroy(p->global); p->global = NULL; if (avrule_block_read(p, &p->global, info->sym_num, fp) == -1) { goto bad; } if (p->global == NULL) { ERR(fp->handle, "no avrule block in policy"); goto bad; } for (i = 0; i < info->sym_num; i++) { if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } nel = le32_to_cpu(buf[0]); for (j = 0; j < nel; j++) { if (scope_read(p, i, fp)) goto bad; } } } if (policydb_index_decls(fp->handle, p)) goto bad; if (policydb_index_classes(p)) goto bad; if (policydb_index_others(fp->handle, p, verbose)) goto bad; if (ocontext_read(info, p, fp) == -1) { goto bad; } if (genfs_read(p, fp) == -1) { goto bad; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) { if (range_read(p, fp)) { goto bad; } } if (policy_type == POLICY_KERN) { p->type_attr_map = malloc(p->p_types.nprim * sizeof(ebitmap_t)); p->attr_type_map = malloc(p->p_types.nprim * sizeof(ebitmap_t)); if (!p->type_attr_map || !p->attr_type_map) goto bad; for (i = 0; i < p->p_types.nprim; i++) { ebitmap_init(&p->type_attr_map[i]); ebitmap_init(&p->attr_type_map[i]); } for (i = 0; i < p->p_types.nprim; i++) { if (r_policyvers >= POLICYDB_VERSION_AVTAB) { if (ebitmap_read(&p->type_attr_map[i], fp)) goto bad; ebitmap_for_each_bit(&p->type_attr_map[i], tnode, j) { if (!ebitmap_node_get_bit(tnode, j) || i == j) continue; if (j >= p->p_types.nprim) goto bad; if (ebitmap_set_bit (&p->attr_type_map[j], i, 1)) goto bad; } } /* add the type itself as the degenerate case */ if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) goto bad; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&p->attr_type_map[i], i, 1)) goto bad; } } } return POLICYDB_SUCCESS; bad: return POLICYDB_ERROR; } int policydb_reindex_users(policydb_t * p) { unsigned int i = SYM_USERS; if (p->user_val_to_struct) free(p->user_val_to_struct); if (p->sym_val_to_name[i]) free(p->sym_val_to_name[i]); p->user_val_to_struct = (user_datum_t **) calloc(p->p_users.nprim, sizeof(user_datum_t *)); if (!p->user_val_to_struct) return -1; p->sym_val_to_name[i] = (char **) calloc(p->symtab[i].nprim, sizeof(char *)); if (!p->sym_val_to_name[i]) return -1; if (hashtab_map(p->symtab[i].table, index_f[i], p)) return -1; /* Expand user roles for context validity checking */ if (hashtab_map(p->p_users.table, policydb_user_cache, p)) return -1; return 0; } void policy_file_init(policy_file_t *pf) { memset(pf, 0, sizeof(policy_file_t)); } int policydb_set_target_platform(policydb_t *p, int platform) { if (platform == SEPOL_TARGET_SELINUX) p->target_platform = SEPOL_TARGET_SELINUX; else if (platform == SEPOL_TARGET_XEN) p->target_platform = SEPOL_TARGET_XEN; else return -1; return 0; } int policydb_sort_ocontexts(policydb_t *p) { return sort_ocontexts(p); } libsepol/src/policydb_convert.c0100644 0000000 0000000 00000004072 13756670065 015740 0ustar000000000 0000000 #include #include "private.h" #include "debug.h" #include /* Construct a policydb from the supplied (data, len) pair */ int policydb_from_image(sepol_handle_t * handle, void *data, size_t len, policydb_t * policydb) { policy_file_t pf; policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; pf.handle = handle; if (policydb_read(policydb, &pf, 0)) { policydb_destroy(policydb); ERR(handle, "policy image is invalid"); errno = EINVAL; return STATUS_ERR; } return STATUS_SUCCESS; } /* Write a policydb to a memory region, and return the (data, len) pair. */ int policydb_to_image(sepol_handle_t * handle, policydb_t * policydb, void **newdata, size_t * newlen) { void *tmp_data = NULL; size_t tmp_len; policy_file_t pf; struct policydb tmp_policydb; /* Compute the length for the new policy image. */ policy_file_init(&pf); pf.type = PF_LEN; pf.handle = handle; if (policydb_write(policydb, &pf)) { ERR(handle, "could not compute policy length"); errno = EINVAL; goto err; } /* Allocate the new policy image. */ pf.type = PF_USE_MEMORY; pf.data = malloc(pf.len); if (!pf.data) { ERR(handle, "out of memory"); goto err; } /* Need to save len and data prior to modification by policydb_write. */ tmp_len = pf.len; tmp_data = pf.data; /* Write out the new policy image. */ if (policydb_write(policydb, &pf)) { ERR(handle, "could not write policy"); errno = EINVAL; goto err; } /* Verify the new policy image. */ pf.type = PF_USE_MEMORY; pf.data = tmp_data; pf.len = tmp_len; if (policydb_init(&tmp_policydb)) { ERR(handle, "Out of memory"); errno = ENOMEM; goto err; } if (policydb_read(&tmp_policydb, &pf, 0)) { ERR(handle, "new policy image is invalid"); errno = EINVAL; goto err; } policydb_destroy(&tmp_policydb); /* Update (newdata, newlen) */ *newdata = tmp_data; *newlen = tmp_len; /* Recover */ return STATUS_SUCCESS; err: ERR(handle, "could not create policy image"); /* Recover */ free(tmp_data); return STATUS_ERR; } libsepol/src/policydb_internal.h0100644 0000000 0000000 00000000366 13756670065 016103 0ustar000000000 0000000 #ifndef _SEPOL_POLICYDB_INTERNAL_H_ #define _SEPOL_POLICYDB_INTERNAL_H_ #include #include "dso.h" hidden_proto(sepol_policydb_create) hidden_proto(sepol_policydb_free) extern const char *policydb_target_strings[]; #endif libsepol/src/policydb_public.c0100644 0000000 0000000 00000007671 13756670065 015546 0ustar000000000 0000000 #include #include "debug.h" #include #include "policydb_internal.h" /* Policy file interfaces. */ int sepol_policy_file_create(sepol_policy_file_t ** pf) { *pf = calloc(1, sizeof(sepol_policy_file_t)); if (!(*pf)) return -1; return 0; } void sepol_policy_file_set_mem(sepol_policy_file_t * spf, char *data, size_t len) { struct policy_file *pf = &spf->pf; if (!len) { pf->type = PF_LEN; return; } pf->type = PF_USE_MEMORY; pf->data = data; pf->len = len; pf->size = len; return; } void sepol_policy_file_set_fp(sepol_policy_file_t * spf, FILE * fp) { struct policy_file *pf = &spf->pf; pf->type = PF_USE_STDIO; pf->fp = fp; return; } int sepol_policy_file_get_len(sepol_policy_file_t * spf, size_t * len) { struct policy_file *pf = &spf->pf; if (pf->type != PF_LEN) return -1; *len = pf->len; return 0; } void sepol_policy_file_set_handle(sepol_policy_file_t * pf, sepol_handle_t * handle) { pf->pf.handle = handle; } void sepol_policy_file_free(sepol_policy_file_t * pf) { free(pf); } /* Policydb interfaces. */ int sepol_policydb_create(sepol_policydb_t ** sp) { policydb_t *p; *sp = malloc(sizeof(sepol_policydb_t)); if (!(*sp)) return -1; p = &(*sp)->p; if (policydb_init(p)) { free(*sp); return -1; } return 0; } hidden_def(sepol_policydb_create) void sepol_policydb_free(sepol_policydb_t * p) { if (!p) return; policydb_destroy(&p->p); free(p); } hidden_def(sepol_policydb_free) int sepol_policy_kern_vers_min(void) { return POLICYDB_VERSION_MIN; } int sepol_policy_kern_vers_max(void) { return POLICYDB_VERSION_MAX; } int sepol_policydb_set_typevers(sepol_policydb_t * sp, unsigned int type) { struct policydb *p = &sp->p; switch (type) { case POLICY_KERN: p->policyvers = POLICYDB_VERSION_MAX; break; case POLICY_BASE: case POLICY_MOD: p->policyvers = MOD_POLICYDB_VERSION_MAX; break; default: return -1; } p->policy_type = type; return 0; } int sepol_policydb_set_vers(sepol_policydb_t * sp, unsigned int vers) { struct policydb *p = &sp->p; switch (p->policy_type) { case POLICY_KERN: if (vers < POLICYDB_VERSION_MIN || vers > POLICYDB_VERSION_MAX) return -1; break; case POLICY_BASE: case POLICY_MOD: if (vers < MOD_POLICYDB_VERSION_MIN || vers > MOD_POLICYDB_VERSION_MAX) return -1; break; default: return -1; } p->policyvers = vers; return 0; } int sepol_policydb_set_handle_unknown(sepol_policydb_t * sp, unsigned int handle_unknown) { struct policydb *p = &sp->p; switch (handle_unknown) { case SEPOL_DENY_UNKNOWN: case SEPOL_REJECT_UNKNOWN: case SEPOL_ALLOW_UNKNOWN: break; default: return -1; } p->handle_unknown = handle_unknown; return 0; } int sepol_policydb_set_target_platform(sepol_policydb_t * sp, int target_platform) { struct policydb *p = &sp->p; switch (target_platform) { case SEPOL_TARGET_SELINUX: case SEPOL_TARGET_XEN: break; default: return -1; } p->target_platform = target_platform; return 0; } int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf) { return policydb_read(&p->p, &pf->pf, 0); } int sepol_policydb_write(sepol_policydb_t * p, sepol_policy_file_t * pf) { return policydb_write(&p->p, &pf->pf); } int sepol_policydb_from_image(sepol_handle_t * handle, void *data, size_t len, sepol_policydb_t * p) { return policydb_from_image(handle, data, len, &p->p); } int sepol_policydb_to_image(sepol_handle_t * handle, sepol_policydb_t * p, void **newdata, size_t * newlen) { return policydb_to_image(handle, &p->p, newdata, newlen); } int sepol_policydb_mls_enabled(const sepol_policydb_t * p) { return p->p.mls; } /* * Enable compatibility mode for SELinux network checks iff * the packet class is not defined in the policy. */ #define PACKET_CLASS_NAME "packet" int sepol_policydb_compat_net(const sepol_policydb_t * p) { return (hashtab_search(p->p.p_classes.table, PACKET_CLASS_NAME) == NULL); } libsepol/src/port_internal.h0100644 0000000 0000000 00000001131 13756670065 015251 0ustar000000000 0000000 #ifndef _SEPOL_PORT_INTERNAL_H_ #define _SEPOL_PORT_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_port_create) hidden_proto(sepol_port_free) hidden_proto(sepol_port_get_con) hidden_proto(sepol_port_get_high) hidden_proto(sepol_port_get_low) hidden_proto(sepol_port_get_proto) hidden_proto(sepol_port_get_proto_str) hidden_proto(sepol_port_key_create) hidden_proto(sepol_port_key_unpack) hidden_proto(sepol_port_set_con) hidden_proto(sepol_port_set_proto) hidden_proto(sepol_port_set_range) #endif libsepol/src/port_record.c0100644 0000000 0000000 00000012050 13756670065 014710 0ustar000000000 0000000 #include #include #include "port_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_port { /* Low - High range. Same for single ports. */ int low, high; /* Protocol */ int proto; /* Context */ sepol_context_t *con; }; struct sepol_port_key { /* Low - High range. Same for single ports. */ int low, high; /* Protocol */ int proto; }; /* Key */ int sepol_port_key_create(sepol_handle_t * handle, int low, int high, int proto, sepol_port_key_t ** key_ptr) { sepol_port_key_t *tmp_key = (sepol_port_key_t *) malloc(sizeof(sepol_port_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create " "port key"); return STATUS_ERR; } tmp_key->low = low; tmp_key->high = high; tmp_key->proto = proto; *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(sepol_port_key_create) void sepol_port_key_unpack(const sepol_port_key_t * key, int *low, int *high, int *proto) { *low = key->low; *high = key->high; *proto = key->proto; } hidden_def(sepol_port_key_unpack) int sepol_port_key_extract(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_key_t ** key_ptr) { if (sepol_port_key_create (handle, port->low, port->high, port->proto, key_ptr) < 0) { ERR(handle, "could not extract key from port %s %d:%d", sepol_port_get_proto_str(port->proto), port->low, port->high); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_port_key_free(sepol_port_key_t * key) { free(key); } int sepol_port_compare(const sepol_port_t * port, const sepol_port_key_t * key) { if ((port->low == key->low) && (port->high == key->high) && (port->proto == key->proto)) return 0; if (port->low < key->low) return -1; else if (key->low < port->low) return 1; else if (port->high < key->high) return -1; else if (key->high < port->high) return 1; else if (port->proto < key->proto) return -1; else return 1; } int sepol_port_compare2(const sepol_port_t * port, const sepol_port_t * port2) { if ((port->low == port2->low) && (port->high == port2->high) && (port->proto == port2->proto)) return 0; if (port->low < port2->low) return -1; else if (port2->low < port->low) return 1; else if (port->high < port2->high) return -1; else if (port2->high < port->high) return 1; else if (port->proto < port2->proto) return -1; else return 1; } /* Port */ int sepol_port_get_low(const sepol_port_t * port) { return port->low; } hidden_def(sepol_port_get_low) int sepol_port_get_high(const sepol_port_t * port) { return port->high; } hidden_def(sepol_port_get_high) void sepol_port_set_port(sepol_port_t * port, int port_num) { port->low = port_num; port->high = port_num; } void sepol_port_set_range(sepol_port_t * port, int low, int high) { port->low = low; port->high = high; } hidden_def(sepol_port_set_range) /* Protocol */ int sepol_port_get_proto(const sepol_port_t * port) { return port->proto; } hidden_def(sepol_port_get_proto) const char *sepol_port_get_proto_str(int proto) { switch (proto) { case SEPOL_PROTO_UDP: return "udp"; case SEPOL_PROTO_TCP: return "tcp"; case SEPOL_PROTO_DCCP: return "dccp"; case SEPOL_PROTO_SCTP: return "sctp"; default: return "???"; } } hidden_def(sepol_port_get_proto_str) void sepol_port_set_proto(sepol_port_t * port, int proto) { port->proto = proto; } hidden_def(sepol_port_set_proto) /* Create */ int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port) { sepol_port_t *tmp_port = (sepol_port_t *) malloc(sizeof(sepol_port_t)); if (!tmp_port) { ERR(handle, "out of memory, could not create " "port record"); return STATUS_ERR; } tmp_port->low = 0; tmp_port->high = 0; tmp_port->proto = SEPOL_PROTO_UDP; tmp_port->con = NULL; *port = tmp_port; return STATUS_SUCCESS; } hidden_def(sepol_port_create) /* Deep copy clone */ int sepol_port_clone(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_t ** port_ptr) { sepol_port_t *new_port = NULL; if (sepol_port_create(handle, &new_port) < 0) goto err; new_port->low = port->low; new_port->high = port->high; new_port->proto = port->proto; if (port->con && (sepol_context_clone(handle, port->con, &new_port->con) < 0)) goto err; *port_ptr = new_port; return STATUS_SUCCESS; err: ERR(handle, "could not clone port record"); sepol_port_free(new_port); return STATUS_ERR; } /* Destroy */ void sepol_port_free(sepol_port_t * port) { if (!port) return; sepol_context_free(port->con); free(port); } hidden_def(sepol_port_free) /* Context */ sepol_context_t *sepol_port_get_con(const sepol_port_t * port) { return port->con; } hidden_def(sepol_port_get_con) int sepol_port_set_con(sepol_handle_t * handle, sepol_port_t * port, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set port context"); return STATUS_ERR; } sepol_context_free(port->con); port->con = newcon; return STATUS_SUCCESS; } hidden_def(sepol_port_set_con) libsepol/src/ports.c0100644 0000000 0000000 00000016344 13756670065 013547 0ustar000000000 0000000 #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "port_internal.h" static inline int sepol2ipproto(sepol_handle_t * handle, int proto) { switch (proto) { case SEPOL_PROTO_TCP: return IPPROTO_TCP; case SEPOL_PROTO_UDP: return IPPROTO_UDP; case SEPOL_PROTO_DCCP: return IPPROTO_DCCP; case SEPOL_PROTO_SCTP: return IPPROTO_SCTP; default: ERR(handle, "unsupported protocol %u", proto); return STATUS_ERR; } } static inline int ipproto2sepol(sepol_handle_t * handle, int proto) { switch (proto) { case IPPROTO_TCP: return SEPOL_PROTO_TCP; case IPPROTO_UDP: return SEPOL_PROTO_UDP; case IPPROTO_DCCP: return SEPOL_PROTO_DCCP; case IPPROTO_SCTP: return SEPOL_PROTO_SCTP; default: ERR(handle, "invalid protocol %u " "found in policy", proto); return STATUS_ERR; } } /* Create a low level port structure from * a high level representation */ static int port_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** port, const sepol_port_t * data) { ocontext_t *tmp_port = NULL; context_struct_t *tmp_con = NULL; int tmp_proto; int low = sepol_port_get_low(data); int high = sepol_port_get_high(data); int proto = sepol_port_get_proto(data); tmp_port = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_port) goto omem; /* Process protocol */ tmp_proto = sepol2ipproto(handle, proto); if (tmp_proto < 0) goto err; tmp_port->u.port.protocol = tmp_proto; /* Port range */ tmp_port->u.port.low_port = low; tmp_port->u.port.high_port = high; if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) { ERR(handle, "low port %d exceeds high port %d", tmp_port->u.port.low_port, tmp_port->u.port.high_port); goto err; } /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_port_get_con(data)) < 0) goto err; context_cpy(&tmp_port->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *port = tmp_port; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_port != NULL) { context_destroy(&tmp_port->context[0]); free(tmp_port); } context_destroy(tmp_con); free(tmp_con); ERR(handle, "could not create port structure for range %u:%u (%s)", low, high, sepol_port_get_proto_str(proto)); return STATUS_ERR; } static int port_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * port, sepol_port_t ** record) { int proto = port->u.port.protocol; int low = port->u.port.low_port; int high = port->u.port.high_port; context_struct_t *con = &port->context[0]; int rec_proto = -1; sepol_context_t *tmp_con = NULL; sepol_port_t *tmp_record = NULL; if (sepol_port_create(handle, &tmp_record) < 0) goto err; rec_proto = ipproto2sepol(handle, proto); if (rec_proto < 0) goto err; sepol_port_set_proto(tmp_record, rec_proto); sepol_port_set_range(tmp_record, low, high); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert port range %u - %u (%s) " "to record", low, high, sepol_port_get_proto_str(rec_proto)); sepol_context_free(tmp_con); sepol_port_free(tmp_record); return STATUS_ERR; } /* Return the number of ports */ extern int sepol_port_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_PORT]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a port exists */ int sepol_port_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_port_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int proto2 = c->u.port.protocol; int low2 = c->u.port.low_port; int high2 = c->u.port.high_port; if (proto == proto2 && low2 == low && high2 == high) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; err: ERR(handle, "could not check if port range %u - %u (%s) exists", low, high, proto_str); return STATUS_ERR; } /* Query a port */ int sepol_port_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_port_key_t * key, sepol_port_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int proto2 = c->u.port.protocol; int low2 = c->u.port.low_port; int high2 = c->u.port.high_port; if (proto == proto2 && low2 == low && high2 == high) { if (port_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query port range %u - %u (%s)", low, high, proto_str); return STATUS_ERR; } /* Load a port into policy */ int sepol_port_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_port_key_t * key, const sepol_port_t * data) { policydb_t *policydb = &p->p; ocontext_t *port = NULL; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; if (port_from_record(handle, policydb, &port, data) < 0) goto err; /* Attach to context list */ port->next = policydb->ocontexts[OCON_PORT]; policydb->ocontexts[OCON_PORT] = port; return STATUS_SUCCESS; err: ERR(handle, "could not load port range %u - %u (%s)", low, high, proto_str); if (port != NULL) { context_destroy(&port->context[0]); free(port); } return STATUS_ERR; } int sepol_port_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_port_t * port, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_port_t *port = NULL; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int status; if (port_to_record(handle, policydb, c, &port) < 0) goto err; /* Invoke handler */ status = fn(port, arg); if (status < 0) goto err; sepol_port_free(port); port = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ports"); sepol_port_free(port); return STATUS_ERR; } libsepol/src/private.h0100644 0000000 0000000 00000003302 13756670065 014045 0ustar000000000 0000000 /* Private definitions for libsepol. */ /* Endian conversion for reading and writing binary policies */ #include #ifdef __APPLE__ #include #include #else #include #include #endif #include #include #ifdef __APPLE__ #define __BYTE_ORDER BYTE_ORDER #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le16(x) (x) #define le16_to_cpu(x) (x) #define cpu_to_le32(x) (x) #define le32_to_cpu(x) (x) #define cpu_to_le64(x) (x) #define le64_to_cpu(x) (x) #else #define cpu_to_le16(x) bswap_16(x) #define le16_to_cpu(x) bswap_16(x) #define cpu_to_le32(x) bswap_32(x) #define le32_to_cpu(x) bswap_32(x) #define cpu_to_le64(x) bswap_64(x) #define le64_to_cpu(x) bswap_64(x) #endif #undef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #undef max #define max(a,b) ((a) >= (b) ? (a) : (b)) #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) #define is_saturated(x) (x == (typeof(x))-1) #define zero_or_saturated(x) ((x == 0) || is_saturated(x)) /* Policy compatibility information. */ struct policydb_compat_info { unsigned int type; unsigned int version; unsigned int sym_num; unsigned int ocon_num; unsigned int target_platform; }; extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version, unsigned int type, unsigned int target_platform); /* Reading from a policy "file". */ extern int next_entry(void *buf, struct policy_file *fp, size_t bytes) hidden; extern size_t put_entry(const void *ptr, size_t size, size_t n, struct policy_file *fp) hidden; extern int str_read(char **strp, struct policy_file *fp, size_t len) hidden; libsepol/src/roles.c0100644 0000000 0000000 00000002233 13756670065 013514 0ustar000000000 0000000 #include #include #include #include #include "debug.h" #include "handle.h" /* Check if a role exists */ int sepol_role_exists(sepol_handle_t * handle __attribute__ ((unused)), sepol_policydb_t * p, const char *role, int *response) { policydb_t *policydb = &p->p; *response = (hashtab_search(policydb->p_roles.table, role) != NULL); return STATUS_SUCCESS; } /* Fill an array with all valid roles */ int sepol_role_list(sepol_handle_t * handle, sepol_policydb_t * p, char ***roles, unsigned int *nroles) { policydb_t *policydb = &p->p; unsigned int tmp_nroles = policydb->p_roles.nprim; char **tmp_roles = (char **)malloc(tmp_nroles * sizeof(char *)); char **ptr; unsigned int i; if (!tmp_roles) goto omem; for (i = 0; i < tmp_nroles; i++) { tmp_roles[i] = strdup(policydb->p_role_val_to_name[i]); if (!tmp_roles[i]) goto omem; } *nroles = tmp_nroles; *roles = tmp_roles; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not list roles"); ptr = tmp_roles; while (ptr && *ptr) free(*ptr++); free(tmp_roles); return STATUS_ERR; } libsepol/src/services.c0100644 0000000 0000000 00000157631 13756670065 014230 0ustar000000000 0000000 /* * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer * and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2003 - 2004 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the security services. */ /* Initial sizes malloc'd for sepol_compute_av_reason_buffer() support */ #define REASON_BUF_SIZE 2048 #define EXPR_BUF_SIZE 1024 #define STACK_LEN 32 #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" #include "context.h" #include "av_permissions.h" #include "dso.h" #include "mls.h" #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) #define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) static int selinux_enforcing = 1; static sidtab_t mysidtab, *sidtab = &mysidtab; static policydb_t mypolicydb, *policydb = &mypolicydb; /* Used by sepol_compute_av_reason_buffer() to keep track of entries */ static int reason_buf_used; static int reason_buf_len; /* Stack services for RPN to infix conversion. */ static char **stack; static int stack_len; static int next_stack_entry; static void push(char *expr_ptr) { if (next_stack_entry >= stack_len) { char **new_stack = stack; int new_stack_len; if (stack_len == 0) new_stack_len = STACK_LEN; else new_stack_len = stack_len * 2; new_stack = realloc(stack, new_stack_len * sizeof(*stack)); if (!new_stack) { ERR(NULL, "unable to allocate stack space"); return; } stack_len = new_stack_len; stack = new_stack; } stack[next_stack_entry] = expr_ptr; next_stack_entry++; } static char *pop(void) { next_stack_entry--; if (next_stack_entry < 0) { next_stack_entry = 0; ERR(NULL, "pop called with no stack entries"); return NULL; } return stack[next_stack_entry]; } /* End Stack services */ int hidden sepol_set_sidtab(sidtab_t * s) { sidtab = s; return 0; } int hidden sepol_set_policydb(policydb_t * p) { policydb = p; return 0; } int sepol_set_policydb_from_file(FILE * fp) { struct policy_file pf; policy_file_init(&pf); pf.fp = fp; pf.type = PF_USE_STDIO; if (mypolicydb.policy_type) policydb_destroy(&mypolicydb); if (policydb_init(&mypolicydb)) { ERR(NULL, "Out of memory!"); return -1; } if (policydb_read(&mypolicydb, &pf, 0)) { policydb_destroy(&mypolicydb); ERR(NULL, "can't read binary policy: %s", strerror(errno)); return -1; } policydb = &mypolicydb; return sepol_sidtab_init(sidtab); } /* * The largest sequence number that has been used when * providing an access decision to the access vector cache. * The sequence number only changes when a policy change * occurs. */ static uint32_t latest_granting = 0; /* * cat_expr_buf adds a string to an expression buffer and handles * realloc's if buffer is too small. The array of expression text * buffer pointers and its counter are globally defined here as * constraint_expr_eval_reason() sets them up and cat_expr_buf * updates the e_buf pointer. */ static int expr_counter; static char **expr_list; static int expr_buf_used; static int expr_buf_len; static void cat_expr_buf(char *e_buf, const char *string) { int len, new_buf_len; char *p, *new_buf = e_buf; while (1) { p = e_buf + expr_buf_used; len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string); if (len < 0 || len >= expr_buf_len - expr_buf_used) { new_buf_len = expr_buf_len + EXPR_BUF_SIZE; new_buf = realloc(e_buf, new_buf_len); if (!new_buf) { ERR(NULL, "failed to realloc expr buffer"); return; } /* Update new ptr in expr list and locally + new len */ expr_list[expr_counter] = new_buf; e_buf = new_buf; expr_buf_len = new_buf_len; } else { expr_buf_used += len; return; } } } /* * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES, * then for 'types' only, read the types_names->types list as it will * contain a list of types and attributes that were defined in the * policy source. * For user and role plus types (for policy vers < * POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list. */ static void get_name_list(constraint_expr_t *e, int type, const char *src, const char *op, int failed) { ebitmap_t *types; int rc = 0; unsigned int i; char tmp_buf[128]; int counter = 0; if (policydb->policy_type == POLICY_KERN && policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && type == CEXPR_TYPE) types = &e->type_names->types; else types = &e->names; /* Find out how many entries */ for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { rc = ebitmap_get_bit(types, i); if (rc == 0) continue; else counter++; } snprintf(tmp_buf, sizeof(tmp_buf), "(%s%s", src, op); cat_expr_buf(expr_list[expr_counter], tmp_buf); if (counter == 0) cat_expr_buf(expr_list[expr_counter], " "); if (counter > 1) cat_expr_buf(expr_list[expr_counter], " {"); if (counter >= 1) { for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { rc = ebitmap_get_bit(types, i); if (rc == 0) continue; /* Collect entries */ switch (type) { case CEXPR_USER: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_user_val_to_name[i]); break; case CEXPR_ROLE: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_role_val_to_name[i]); break; case CEXPR_TYPE: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_type_val_to_name[i]); break; } cat_expr_buf(expr_list[expr_counter], tmp_buf); } } if (counter > 1) cat_expr_buf(expr_list[expr_counter], " }"); if (failed) cat_expr_buf(expr_list[expr_counter], " -Fail-) "); else cat_expr_buf(expr_list[expr_counter], ") "); return; } static void msgcat(const char *src, const char *tgt, const char *op, int failed) { char tmp_buf[128]; if (failed) snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ", src, op, tgt); else snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s) ", src, op, tgt); cat_expr_buf(expr_list[expr_counter], tmp_buf); } /* Returns a buffer with class, statement type and permissions */ static char *get_class_info(sepol_security_class_t tclass, constraint_node_t *constraint, context_struct_t *xcontext) { constraint_expr_t *e; int mls, state_num; /* Find if MLS statement or not */ mls = 0; for (e = constraint->expr; e; e = e->next) { if (e->attr >= CEXPR_L1L2) { mls = 1; break; } } /* Determine statement type */ const char *statements[] = { "constrain ", /* 0 */ "mlsconstrain ", /* 1 */ "validatetrans ", /* 2 */ "mlsvalidatetrans ", /* 3 */ 0 }; if (xcontext == NULL) state_num = mls + 0; else state_num = mls + 2; int class_buf_len = 0; int new_class_buf_len; int len, buf_used; char *class_buf = NULL, *p; char *new_class_buf = NULL; while (1) { new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; new_class_buf = realloc(class_buf, new_class_buf_len); if (!new_class_buf) return NULL; class_buf_len = new_class_buf_len; class_buf = new_class_buf; buf_used = 0; p = class_buf; /* Add statement type */ len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); if (len < 0 || len >= class_buf_len - buf_used) continue; /* Add class entry */ p += len; buf_used += len; len = snprintf(p, class_buf_len - buf_used, "%s ", policydb->p_class_val_to_name[tclass - 1]); if (len < 0 || len >= class_buf_len - buf_used) continue; /* Add permission entries (validatetrans does not have perms) */ p += len; buf_used += len; if (state_num < 2) { len = snprintf(p, class_buf_len - buf_used, "{%s } (", sepol_av_to_string(policydb, tclass, constraint->permissions)); } else { len = snprintf(p, class_buf_len - buf_used, "("); } if (len < 0 || len >= class_buf_len - buf_used) continue; break; } return class_buf; } /* * Modified version of constraint_expr_eval that will process each * constraint as before but adds the information to text buffers that * will hold various components. The expression will be in RPN format, * therefore there is a stack based RPN to infix converter to produce * the final readable constraint. * * Return the boolean value of a constraint expression * when it is applied to the specified source and target * security contexts. * * xcontext is a special beast... It is used by the validatetrans rules * only. For these rules, scontext is the context before the transition, * tcontext is the context after the transition, and xcontext is the * context of the process performing the transition. All other callers * of constraint_expr_eval_reason should pass in NULL for xcontext. * * This function will also build a buffer as the constraint is processed * for analysis. If this option is not required, then: * 'tclass' should be '0' and r_buf MUST be NULL. */ static int constraint_expr_eval_reason(context_struct_t *scontext, context_struct_t *tcontext, context_struct_t *xcontext, sepol_security_class_t tclass, constraint_node_t *constraint, char **r_buf, unsigned int flags) { uint32_t val1, val2; context_struct_t *c; role_datum_t *r1, *r2; mls_level_t *l1, *l2; constraint_expr_t *e; int s[CEXPR_MAXDEPTH]; int sp = -1; char tmp_buf[128]; /* * Define the s_t_x_num values that make up r1, t2 etc. in text strings * Set 1 = source, 2 = target, 3 = xcontext for validatetrans */ #define SOURCE 1 #define TARGET 2 #define XTARGET 3 int s_t_x_num = SOURCE; /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ int u_r_t = 0; char *src = NULL; char *tgt = NULL; int rc = 0, x; char *class_buf = NULL; /* * The array of expression answer buffer pointers and counter. */ char **answer_list = NULL; int answer_counter = 0; class_buf = get_class_info(tclass, constraint, xcontext); if (!class_buf) { ERR(NULL, "failed to allocate class buffer"); return -ENOMEM; } /* Original function but with buffer support */ int expr_list_len = 0; expr_counter = 0; expr_list = NULL; for (e = constraint->expr; e; e = e->next) { /* Allocate a stack to hold expression buffer entries */ if (expr_counter >= expr_list_len) { char **new_expr_list = expr_list; int new_expr_list_len; if (expr_list_len == 0) new_expr_list_len = STACK_LEN; else new_expr_list_len = expr_list_len * 2; new_expr_list = realloc(expr_list, new_expr_list_len * sizeof(*expr_list)); if (!new_expr_list) { ERR(NULL, "failed to allocate expr buffer stack"); rc = -ENOMEM; goto out; } expr_list_len = new_expr_list_len; expr_list = new_expr_list; } /* * malloc a buffer to store each expression text component. If * buffer is too small cat_expr_buf() will realloc extra space. */ expr_buf_len = EXPR_BUF_SIZE; expr_list[expr_counter] = malloc(expr_buf_len); if (!expr_list[expr_counter]) { ERR(NULL, "failed to allocate expr buffer"); rc = -ENOMEM; goto out; } expr_buf_used = 0; /* Now process each expression of the constraint */ switch (e->expr_type) { case CEXPR_NOT: BUG_ON(sp < 0); s[sp] = !s[sp]; cat_expr_buf(expr_list[expr_counter], "not"); break; case CEXPR_AND: BUG_ON(sp < 1); sp--; s[sp] &= s[sp + 1]; cat_expr_buf(expr_list[expr_counter], "and"); break; case CEXPR_OR: BUG_ON(sp < 1); sp--; s[sp] |= s[sp + 1]; cat_expr_buf(expr_list[expr_counter], "or"); break; case CEXPR_ATTR: if (sp == (CEXPR_MAXDEPTH - 1)) goto out; switch (e->attr) { case CEXPR_USER: val1 = scontext->user; val2 = tcontext->user; free(src); src = strdup("u1"); free(tgt); tgt = strdup("u2"); break; case CEXPR_TYPE: val1 = scontext->type; val2 = tcontext->type; free(src); src = strdup("t1"); free(tgt); tgt = strdup("t2"); break; case CEXPR_ROLE: val1 = scontext->role; val2 = tcontext->role; r1 = policydb->role_val_to_struct[val1 - 1]; r2 = policydb->role_val_to_struct[val2 - 1]; free(src); src = strdup("r1"); free(tgt); tgt = strdup("r2"); switch (e->op) { case CEXPR_DOM: s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); msgcat(src, tgt, "dom", s[sp] == 0); expr_counter++; continue; case CEXPR_DOMBY: s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); msgcat(src, tgt, "domby", s[sp] == 0); expr_counter++; continue; case CEXPR_INCOMP: s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1) && !ebitmap_get_bit(&r2->dominates, val1 - 1)); msgcat(src, tgt, "incomp", s[sp] == 0); expr_counter++; continue; default: break; } break; case CEXPR_L1L2: l1 = &(scontext->range.level[0]); l2 = &(tcontext->range.level[0]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("l2"); goto mls_ops; case CEXPR_L1H2: l1 = &(scontext->range.level[0]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("h2"); goto mls_ops; case CEXPR_H1L2: l1 = &(scontext->range.level[1]); l2 = &(tcontext->range.level[0]); free(src); src = strdup("h1"); free(tgt); tgt = strdup("l2"); goto mls_ops; case CEXPR_H1H2: l1 = &(scontext->range.level[1]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("h1"); free(tgt); tgt = strdup("h2"); goto mls_ops; case CEXPR_L1H1: l1 = &(scontext->range.level[0]); l2 = &(scontext->range.level[1]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("h1"); goto mls_ops; case CEXPR_L2H2: l1 = &(tcontext->range.level[0]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("l2"); free(tgt); tgt = strdup("h2"); mls_ops: switch (e->op) { case CEXPR_EQ: s[++sp] = mls_level_eq(l1, l2); msgcat(src, tgt, "eq", s[sp] == 0); expr_counter++; continue; case CEXPR_NEQ: s[++sp] = !mls_level_eq(l1, l2); msgcat(src, tgt, "!=", s[sp] == 0); expr_counter++; continue; case CEXPR_DOM: s[++sp] = mls_level_dom(l1, l2); msgcat(src, tgt, "dom", s[sp] == 0); expr_counter++; continue; case CEXPR_DOMBY: s[++sp] = mls_level_dom(l2, l1); msgcat(src, tgt, "domby", s[sp] == 0); expr_counter++; continue; case CEXPR_INCOMP: s[++sp] = mls_level_incomp(l2, l1); msgcat(src, tgt, "incomp", s[sp] == 0); expr_counter++; continue; default: BUG(); goto out; } break; default: BUG(); goto out; } switch (e->op) { case CEXPR_EQ: s[++sp] = (val1 == val2); msgcat(src, tgt, "==", s[sp] == 0); break; case CEXPR_NEQ: s[++sp] = (val1 != val2); msgcat(src, tgt, "!=", s[sp] == 0); break; default: BUG(); goto out; } break; case CEXPR_NAMES: if (sp == (CEXPR_MAXDEPTH - 1)) goto out; s_t_x_num = SOURCE; c = scontext; if (e->attr & CEXPR_TARGET) { s_t_x_num = TARGET; c = tcontext; } else if (e->attr & CEXPR_XTARGET) { s_t_x_num = XTARGET; c = xcontext; } if (!c) { BUG(); goto out; } if (e->attr & CEXPR_USER) { u_r_t = CEXPR_USER; val1 = c->user; snprintf(tmp_buf, sizeof(tmp_buf), "u%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else if (e->attr & CEXPR_ROLE) { u_r_t = CEXPR_ROLE; val1 = c->role; snprintf(tmp_buf, sizeof(tmp_buf), "r%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else if (e->attr & CEXPR_TYPE) { u_r_t = CEXPR_TYPE; val1 = c->type; snprintf(tmp_buf, sizeof(tmp_buf), "t%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else { BUG(); goto out; } switch (e->op) { case CEXPR_EQ: s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); get_name_list(e, u_r_t, src, "==", s[sp] == 0); break; case CEXPR_NEQ: s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); get_name_list(e, u_r_t, src, "!=", s[sp] == 0); break; default: BUG(); goto out; } break; default: BUG(); goto out; } expr_counter++; } /* * At this point each expression of the constraint is in * expr_list[n+1] and in RPN format. Now convert to 'infix' */ /* * Save expr count but zero expr_counter to detect if * 'BUG(); goto out;' was called as we need to release any used * expr_list malloc's. Normally they are released by the RPN to * infix code. */ int expr_count = expr_counter; expr_counter = 0; /* * Generate the same number of answer buffer entries as expression * buffers (as there will never be more). */ answer_list = malloc(expr_count * sizeof(*answer_list)); if (!answer_list) { ERR(NULL, "failed to allocate answer stack"); rc = -ENOMEM; goto out; } /* The pop operands */ char *a; char *b; int a_len, b_len; /* Convert constraint from RPN to infix notation. */ for (x = 0; x != expr_count; x++) { if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], "or", 2) == 0) { b = pop(); b_len = strlen(b); a = pop(); a_len = strlen(a); /* get a buffer to hold the answer */ answer_list[answer_counter] = malloc(a_len + b_len + 8); if (!answer_list[answer_counter]) { ERR(NULL, "failed to allocate answer buffer"); rc = -ENOMEM; goto out; } memset(answer_list[answer_counter], '\0', a_len + b_len + 8); sprintf(answer_list[answer_counter], "%s %s %s", a, expr_list[x], b); push(answer_list[answer_counter++]); free(a); free(b); free(expr_list[x]); } else if (strncmp(expr_list[x], "not", 3) == 0) { b = pop(); b_len = strlen(b); answer_list[answer_counter] = malloc(b_len + 8); if (!answer_list[answer_counter]) { ERR(NULL, "failed to allocate answer buffer"); rc = -ENOMEM; goto out; } memset(answer_list[answer_counter], '\0', b_len + 8); if (strncmp(b, "not", 3) == 0) sprintf(answer_list[answer_counter], "%s (%s)", expr_list[x], b); else sprintf(answer_list[answer_counter], "%s%s", expr_list[x], b); push(answer_list[answer_counter++]); free(b); free(expr_list[x]); } else { push(expr_list[x]); } } /* Get the final answer from tos and build constraint text */ a = pop(); /* validatetrans / constraint calculation: rc = 0 is denied, rc = 1 is granted */ sprintf(tmp_buf, "%s %s\n", xcontext ? "Validatetrans" : "Constraint", s[0] ? "GRANTED" : "DENIED"); int len, new_buf_len; char *p, **new_buf = r_buf; /* * These contain the constraint components that are added to the * callers reason buffer. */ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; /* * This will add the constraints to the callers reason buffer (who is * responsible for freeing the memory). It will handle any realloc's * should the buffer be too short. * The reason_buf_used and reason_buf_len counters are defined * globally as multiple constraints can be in the buffer. */ if (r_buf && ((s[0] == 0) || ((s[0] == 1 && (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { for (x = 0; buffers[x] != NULL; x++) { while (1) { p = *r_buf + reason_buf_used; len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]); if (len < 0 || len >= reason_buf_len - reason_buf_used) { new_buf_len = reason_buf_len + REASON_BUF_SIZE; *new_buf = realloc(*r_buf, new_buf_len); if (!new_buf) { ERR(NULL, "failed to realloc reason buffer"); goto out1; } **r_buf = **new_buf; reason_buf_len = new_buf_len; continue; } else { reason_buf_used += len; break; } } } } out1: rc = s[0]; free(a); out: free(class_buf); free(src); free(tgt); if (expr_counter) { for (x = 0; expr_list[x] != NULL; x++) free(expr_list[x]); } free(answer_list); free(expr_list); return rc; } /* Forward declaration */ static int context_struct_compute_av(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **r_buf, unsigned int flags); static void type_attribute_bounds_av(context_struct_t *scontext, context_struct_t *tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason) { context_struct_t lo_scontext; context_struct_t lo_tcontext, *tcontextp = tcontext; struct sepol_av_decision lo_avd; type_datum_t *source; type_datum_t *target; sepol_access_vector_t masked = 0; source = policydb->type_val_to_struct[scontext->type - 1]; if (!source->bounds) return; target = policydb->type_val_to_struct[tcontext->type - 1]; memset(&lo_avd, 0, sizeof(lo_avd)); memcpy(&lo_scontext, scontext, sizeof(lo_scontext)); lo_scontext.type = source->bounds; if (target->bounds) { memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext)); lo_tcontext.type = target->bounds; tcontextp = &lo_tcontext; } context_struct_compute_av(&lo_scontext, tcontextp, tclass, requested, &lo_avd, NULL, /* reason intentionally omitted */ NULL, 0); masked = ~lo_avd.allowed & avd->allowed; if (!masked) return; /* no masked permission */ /* mask violated permissions */ avd->allowed &= ~masked; *reason |= SEPOL_COMPUTEAV_BOUNDS; } /* * Compute access vectors based on a context structure pair for * the permissions in a particular class. */ static int context_struct_compute_av(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **r_buf, unsigned int flags) { constraint_node_t *constraint; struct role_allow *ra; avtab_key_t avkey; class_datum_t *tclass_datum; avtab_ptr_t node; ebitmap_t *sattr, *tattr; ebitmap_node_t *snode, *tnode; unsigned int i, j; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; /* * Initialize the access vectors to the default values. */ avd->allowed = 0; avd->decided = 0xffffffff; avd->auditallow = 0; avd->auditdeny = 0xffffffff; avd->seqno = latest_granting; if (reason) *reason = 0; /* * If a specific type enforcement rule was defined for * this permission check, then use it. */ avkey.target_class = tclass; avkey.specified = AVTAB_AV; sattr = &policydb->type_attr_map[scontext->type - 1]; tattr = &policydb->type_attr_map[tcontext->type - 1]; ebitmap_for_each_bit(sattr, snode, i) { if (!ebitmap_node_get_bit(snode, i)) continue; ebitmap_for_each_bit(tattr, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; avkey.source_type = i + 1; avkey.target_type = j + 1; for (node = avtab_search_node(&policydb->te_avtab, &avkey); node != NULL; node = avtab_search_node_next(node, avkey.specified)) { if (node->key.specified == AVTAB_ALLOWED) avd->allowed |= node->datum.data; else if (node->key.specified == AVTAB_AUDITALLOW) avd->auditallow |= node->datum.data; else if (node->key.specified == AVTAB_AUDITDENY) avd->auditdeny &= node->datum.data; } /* Check conditional av table for additional permissions */ cond_compute_av(&policydb->te_cond_avtab, &avkey, avd); } } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_TE; requested &= avd->allowed; } /* * Remove any permissions prohibited by a constraint (this includes * the MLS policy). */ constraint = tclass_datum->constraints; while (constraint) { if ((constraint->permissions & (avd->allowed)) && !constraint_expr_eval_reason(scontext, tcontext, NULL, tclass, constraint, r_buf, flags)) { avd->allowed = (avd->allowed) & ~(constraint->permissions); } constraint = constraint->next; } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_CONS; requested &= avd->allowed; } /* * If checking process transition permission and the * role is changing, then check the (current_role, new_role) * pair. */ if (tclass == SECCLASS_PROCESS && (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && scontext->role != tcontext->role) { for (ra = policydb->role_allow; ra; ra = ra->next) { if (scontext->role == ra->role && tcontext->role == ra->new_role) break; } if (!ra) avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | PROCESS__DYNTRANSITION); } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_RBAC; requested &= avd->allowed; } type_attribute_bounds_av(scontext, tcontext, tclass, requested, avd, reason); return 0; } int hidden sepol_validate_transition(sepol_security_id_t oldsid, sepol_security_id_t newsid, sepol_security_id_t tasksid, sepol_security_class_t tclass) { context_struct_t *ocontext; context_struct_t *ncontext; context_struct_t *tcontext; class_datum_t *tclass_datum; constraint_node_t *constraint; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; ocontext = sepol_sidtab_search(sidtab, oldsid); if (!ocontext) { ERR(NULL, "unrecognized SID %d", oldsid); return -EINVAL; } ncontext = sepol_sidtab_search(sidtab, newsid); if (!ncontext) { ERR(NULL, "unrecognized SID %d", newsid); return -EINVAL; } tcontext = sepol_sidtab_search(sidtab, tasksid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tasksid); return -EINVAL; } constraint = tclass_datum->validatetrans; while (constraint) { if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, 0, constraint, NULL, 0)) { return -EPERM; } constraint = constraint->next; } return 0; } /* * sepol_validate_transition_reason_buffer - the reason buffer is realloc'd * in the constraint_expr_eval_reason() function. */ int hidden sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid, sepol_security_id_t newsid, sepol_security_id_t tasksid, sepol_security_class_t tclass, char **reason_buf, unsigned int flags) { context_struct_t *ocontext; context_struct_t *ncontext; context_struct_t *tcontext; class_datum_t *tclass_datum; constraint_node_t *constraint; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; ocontext = sepol_sidtab_search(sidtab, oldsid); if (!ocontext) { ERR(NULL, "unrecognized SID %d", oldsid); return -EINVAL; } ncontext = sepol_sidtab_search(sidtab, newsid); if (!ncontext) { ERR(NULL, "unrecognized SID %d", newsid); return -EINVAL; } tcontext = sepol_sidtab_search(sidtab, tasksid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tasksid); return -EINVAL; } /* * Set the buffer to NULL as mls/validatetrans may not be processed. * If a buffer is required, then the routines in * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE * chunks (as it gets called for each mls/validatetrans processed). * We just make sure these start from zero. */ *reason_buf = NULL; reason_buf_used = 0; reason_buf_len = 0; constraint = tclass_datum->validatetrans; while (constraint) { if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, tclass, constraint, reason_buf, flags)) { return -EPERM; } constraint = constraint->next; } return 0; } int hidden sepol_compute_av_reason(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason) { context_struct_t *scontext = 0, *tcontext = 0; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized SID %d", ssid); rc = -EINVAL; goto out; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tsid); rc = -EINVAL; goto out; } rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd, reason, NULL, 0); out: return rc; } /* * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd * in the constraint_expr_eval_reason() function. */ int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **reason_buf, unsigned int flags) { context_struct_t *scontext = 0, *tcontext = 0; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized SID %d", ssid); rc = -EINVAL; goto out; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tsid); rc = -EINVAL; goto out; } /* * Set the buffer to NULL as constraints may not be processed. * If a buffer is required, then the routines in * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE * chunks (as it gets called for each constraint processed). * We just make sure these start from zero. */ *reason_buf = NULL; reason_buf_used = 0; reason_buf_len = 0; rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd, reason, reason_buf, flags); out: return rc; } int hidden sepol_compute_av(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd) { unsigned int reason = 0; return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd, &reason); } /* * Return a class ID associated with the class string specified by * class_name. */ int hidden sepol_string_to_security_class(const char *class_name, sepol_security_class_t *tclass) { class_datum_t *tclass_datum; tclass_datum = hashtab_search(policydb->p_classes.table, (hashtab_key_t) class_name); if (!tclass_datum) { ERR(NULL, "unrecognized class %s", class_name); return STATUS_ERR; } *tclass = tclass_datum->s.value; return STATUS_SUCCESS; } /* * Return access vector bit associated with the class ID and permission * string. */ int hidden sepol_string_to_av_perm(sepol_security_class_t tclass, const char *perm_name, sepol_access_vector_t *av) { class_datum_t *tclass_datum; perm_datum_t *perm_datum; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; /* Check for unique perms then the common ones (if any) */ perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->permissions.table, (hashtab_key_t)perm_name); if (perm_datum != NULL) { *av = 0x1 << (perm_datum->s.value - 1); return STATUS_SUCCESS; } if (tclass_datum->comdatum == NULL) goto out; perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->comdatum->permissions.table, (hashtab_key_t)perm_name); if (perm_datum != NULL) { *av = 0x1 << (perm_datum->s.value - 1); return STATUS_SUCCESS; } out: ERR(NULL, "could not convert %s to av bit", perm_name); return STATUS_ERR; } /* * Write the security context string representation of * the context associated with `sid' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ int hidden sepol_sid_to_context(sepol_security_id_t sid, sepol_security_context_t * scontext, size_t * scontext_len) { context_struct_t *context; int rc = 0; context = sepol_sidtab_search(sidtab, sid); if (!context) { ERR(NULL, "unrecognized SID %d", sid); rc = -EINVAL; goto out; } rc = context_to_string(NULL, policydb, context, scontext, scontext_len); out: return rc; } /* * Return a SID associated with the security context that * has the string representation specified by `scontext'. */ int hidden sepol_context_to_sid(const sepol_security_context_t scontext, size_t scontext_len, sepol_security_id_t * sid) { context_struct_t *context = NULL; /* First, create the context */ if (context_from_string(NULL, policydb, &context, scontext, scontext_len) < 0) goto err; /* Obtain the new sid */ if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0)) goto err; context_destroy(context); free(context); return STATUS_SUCCESS; err: if (context) { context_destroy(context); free(context); } ERR(NULL, "could not convert %s to sid", scontext); return STATUS_ERR; } static inline int compute_sid_handle_invalid_context(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, context_struct_t * newcontext) { if (selinux_enforcing) { return -EACCES; } else { sepol_security_context_t s, t, n; size_t slen, tlen, nlen; context_to_string(NULL, policydb, scontext, &s, &slen); context_to_string(NULL, policydb, tcontext, &t, &tlen); context_to_string(NULL, policydb, newcontext, &n, &nlen); ERR(NULL, "invalid context %s for " "scontext=%s tcontext=%s tclass=%s", n, s, t, policydb->p_class_val_to_name[tclass - 1]); free(s); free(t); free(n); return 0; } } static int sepol_compute_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, uint32_t specified, sepol_security_id_t * out_sid) { context_struct_t *scontext = 0, *tcontext = 0, newcontext; struct role_trans *roletr = 0; avtab_key_t avkey; avtab_datum_t *avdatum; avtab_ptr_t node; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized SID %d", ssid); rc = -EINVAL; goto out; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tsid); rc = -EINVAL; goto out; } context_init(&newcontext); /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: case AVTAB_CHANGE: /* Use the process user identity. */ newcontext.user = scontext->user; break; case AVTAB_MEMBER: /* Use the related object owner. */ newcontext.user = tcontext->user; break; } /* Set the role and type to default values. */ switch (tclass) { case SECCLASS_PROCESS: /* Use the current role and type of process. */ newcontext.role = scontext->role; newcontext.type = scontext->type; break; default: /* Use the well-defined object role. */ newcontext.role = OBJECT_R_VAL; /* Use the type of the related object. */ newcontext.type = tcontext->type; } /* Look for a type transition/member/change rule. */ avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; avkey.specified = specified; avdatum = avtab_search(&policydb->te_avtab, &avkey); /* If no permanent rule, also check for enabled conditional rules */ if (!avdatum) { node = avtab_search_node(&policydb->te_cond_avtab, &avkey); for (; node != NULL; node = avtab_search_node_next(node, specified)) { if (node->key.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; } } } if (avdatum) { /* Use the type from the type transition/member/change rule. */ newcontext.type = avdatum->data; } /* Check for class-specific changes. */ switch (tclass) { case SECCLASS_PROCESS: if (specified & AVTAB_TRANSITION) { /* Look for a role transition rule. */ for (roletr = policydb->role_tr; roletr; roletr = roletr->next) { if (roletr->role == scontext->role && roletr->type == tcontext->type) { /* Use the role transition rule. */ newcontext.role = roletr->new_role; break; } } } break; default: break; } /* Set the MLS attributes. This is done last because it may allocate memory. */ rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified, &newcontext); if (rc) goto out; /* Check the validity of the context. */ if (!policydb_context_isvalid(policydb, &newcontext)) { rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass, &newcontext); if (rc) goto out; } /* Obtain the sid for the context. */ rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid); out: context_destroy(&newcontext); return rc; } /* * Compute a SID to use for labeling a new object in the * class `tclass' based on a SID pair. */ int hidden sepol_transition_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); } /* * Compute a SID to use when selecting a member of a * polyinstantiated object of class `tclass' based on * a SID pair. */ int hidden sepol_member_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); } /* * Compute a SID to use for relabeling an object in the * class `tclass' based on a SID pair. */ int hidden sepol_change_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); } /* * Verify that each permission that is defined under the * existing policy is still defined with the same value * in the new policy. */ static int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) { hashtab_t h; perm_datum_t *perdatum, *perdatum2; h = (hashtab_t) p; perdatum = (perm_datum_t *) datum; perdatum2 = (perm_datum_t *) hashtab_search(h, key); if (!perdatum2) { ERR(NULL, "permission %s disappeared", key); return -1; } if (perdatum->s.value != perdatum2->s.value) { ERR(NULL, "the value of permissions %s changed", key); return -1; } return 0; } /* * Verify that each class that is defined under the * existing policy is still defined with the same * attributes in the new policy. */ static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p) { policydb_t *newp; class_datum_t *cladatum, *cladatum2; newp = (policydb_t *) p; cladatum = (class_datum_t *) datum; cladatum2 = (class_datum_t *) hashtab_search(newp->p_classes.table, key); if (!cladatum2) { ERR(NULL, "class %s disappeared", key); return -1; } if (cladatum->s.value != cladatum2->s.value) { ERR(NULL, "the value of class %s changed", key); return -1; } if ((cladatum->comdatum && !cladatum2->comdatum) || (!cladatum->comdatum && cladatum2->comdatum)) { ERR(NULL, "the inherits clause for the access " "vector definition for class %s changed", key); return -1; } if (cladatum->comdatum) { if (hashtab_map (cladatum->comdatum->permissions.table, validate_perm, cladatum2->comdatum->permissions.table)) { ERR(NULL, " in the access vector definition " "for class %s\n", key); return -1; } } if (hashtab_map(cladatum->permissions.table, validate_perm, cladatum2->permissions.table)) { ERR(NULL, " in access vector definition for class %s", key); return -1; } return 0; } /* Clone the SID into the new SID table. */ static int clone_sid(sepol_security_id_t sid, context_struct_t * context, void *arg) { sidtab_t *s = arg; return sepol_sidtab_insert(s, sid, context); } static inline int convert_context_handle_invalid_context(context_struct_t * context) { if (selinux_enforcing) { return -EINVAL; } else { sepol_security_context_t s; size_t len; context_to_string(NULL, policydb, context, &s, &len); ERR(NULL, "context %s is invalid", s); free(s); return 0; } } typedef struct { policydb_t *oldp; policydb_t *newp; } convert_context_args_t; /* * Convert the values in the security context * structure `c' from the values specified * in the policy `p->oldp' to the values specified * in the policy `p->newp'. Verify that the * context is valid under the new policy. */ static int convert_context(sepol_security_id_t key __attribute__ ((unused)), context_struct_t * c, void *p) { convert_context_args_t *args; context_struct_t oldc; role_datum_t *role; type_datum_t *typdatum; user_datum_t *usrdatum; sepol_security_context_t s; size_t len; int rc = -EINVAL; args = (convert_context_args_t *) p; if (context_cpy(&oldc, c)) return -ENOMEM; /* Convert the user. */ usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table, args->oldp-> p_user_val_to_name[c->user - 1]); if (!usrdatum) { goto bad; } c->user = usrdatum->s.value; /* Convert the role. */ role = (role_datum_t *) hashtab_search(args->newp->p_roles.table, args->oldp-> p_role_val_to_name[c->role - 1]); if (!role) { goto bad; } c->role = role->s.value; /* Convert the type. */ typdatum = (type_datum_t *) hashtab_search(args->newp->p_types.table, args->oldp->p_type_val_to_name[c->type - 1]); if (!typdatum) { goto bad; } c->type = typdatum->s.value; rc = mls_convert_context(args->oldp, args->newp, c); if (rc) goto bad; /* Check the validity of the new context. */ if (!policydb_context_isvalid(args->newp, c)) { rc = convert_context_handle_invalid_context(&oldc); if (rc) goto bad; } context_destroy(&oldc); return 0; bad: context_to_string(NULL, policydb, &oldc, &s, &len); context_destroy(&oldc); ERR(NULL, "invalidating context %s", s); free(s); return rc; } /* Reading from a policy "file". */ int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes) { size_t nread; switch (fp->type) { case PF_USE_STDIO: nread = fread(buf, bytes, 1, fp->fp); if (nread != 1) return -1; break; case PF_USE_MEMORY: if (bytes > fp->len) { errno = EOVERFLOW; return -1; } memcpy(buf, fp->data, bytes); fp->data += bytes; fp->len -= bytes; break; default: errno = EINVAL; return -1; } return 0; } size_t hidden put_entry(const void *ptr, size_t size, size_t n, struct policy_file *fp) { size_t bytes = size * n; switch (fp->type) { case PF_USE_STDIO: return fwrite(ptr, size, n, fp->fp); case PF_USE_MEMORY: if (bytes > fp->len) { errno = ENOSPC; return 0; } memcpy(fp->data, ptr, bytes); fp->data += bytes; fp->len -= bytes; return n; case PF_LEN: fp->len += bytes; return n; default: return 0; } return 0; } /* * Reads a string and null terminates it from the policy file. * This is a port of str_read from the SE Linux kernel code. * * It returns: * 0 - Success * -1 - Failure with errno set */ int hidden str_read(char **strp, struct policy_file *fp, size_t len) { int rc; char *str; if (zero_or_saturated(len)) { errno = EINVAL; return -1; } str = malloc(len + 1); if (!str) return -1; /* it's expected the caller should free the str */ *strp = str; /* next_entry sets errno */ rc = next_entry(str, fp, len); if (rc) return rc; str[len] = '\0'; return 0; } /* * Read a new set of configuration data from * a policy database binary representation file. * * Verify that each class that is defined under the * existing policy is still defined with the same * attributes in the new policy. * * Convert the context structures in the SID table to the * new representation and verify that all entries * in the SID table are valid under the new policy. * * Change the active policy database to use the new * configuration data. * * Reset the access vector cache. */ int hidden sepol_load_policy(void *data, size_t len) { policydb_t oldpolicydb, newpolicydb; sidtab_t oldsidtab, newsidtab; convert_context_args_t args; int rc = 0; struct policy_file file, *fp; policy_file_init(&file); file.type = PF_USE_MEMORY; file.data = data; file.len = len; fp = &file; if (policydb_init(&newpolicydb)) return -ENOMEM; if (policydb_read(&newpolicydb, fp, 1)) { policydb_destroy(&mypolicydb); return -EINVAL; } sepol_sidtab_init(&newsidtab); /* Verify that the existing classes did not change. */ if (hashtab_map (policydb->p_classes.table, validate_class, &newpolicydb)) { ERR(NULL, "the definition of an existing class changed"); rc = -EINVAL; goto err; } /* Clone the SID table. */ sepol_sidtab_shutdown(sidtab); if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) { rc = -ENOMEM; goto err; } /* Convert the internal representations of contexts in the new SID table and remove invalid SIDs. */ args.oldp = policydb; args.newp = &newpolicydb; sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args); /* Save the old policydb and SID table to free later. */ memcpy(&oldpolicydb, policydb, sizeof *policydb); sepol_sidtab_set(&oldsidtab, sidtab); /* Install the new policydb and SID table. */ memcpy(policydb, &newpolicydb, sizeof *policydb); sepol_sidtab_set(sidtab, &newsidtab); /* Free the old policydb and SID table. */ policydb_destroy(&oldpolicydb); sepol_sidtab_destroy(&oldsidtab); return 0; err: sepol_sidtab_destroy(&newsidtab); policydb_destroy(&newpolicydb); return rc; } /* * Return the SIDs to use for an unlabeled file system * that is being mounted from the device with the * the kdevname `name'. The `fs_sid' SID is returned for * the file system and the `file_sid' SID is returned * for all files within that file system. */ int hidden sepol_fs_sid(char *name, sepol_security_id_t * fs_sid, sepol_security_id_t * file_sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_FS]; while (c) { if (strcmp(c->u.name, name) == 0) break; c = c->next; } if (c) { if (!c->sid[0] || !c->sid[1]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; rc = sepol_sidtab_context_to_sid(sidtab, &c->context[1], &c->sid[1]); if (rc) goto out; } *fs_sid = c->sid[0]; *file_sid = c->sid[1]; } else { *fs_sid = SECINITSID_FS; *file_sid = SECINITSID_FILE; } out: return rc; } /* * Return the SID of the ibpkey specified by * `subnet prefix', and `pkey number'. */ int hidden sepol_ibpkey_sid(uint64_t subnet_prefix, uint16_t pkey, sepol_security_id_t *out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_IBPKEY]; while (c) { if (c->u.ibpkey.low_pkey <= pkey && c->u.ibpkey.high_pkey >= pkey && subnet_prefix == c->u.ibpkey.subnet_prefix) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_UNLABELED; } out: return rc; } /* * Return the SID of the subnet management interface specified by * `device name', and `port'. */ int hidden sepol_ibendport_sid(char *dev_name, uint8_t port, sepol_security_id_t *out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_IBENDPORT]; while (c) { if (c->u.ibendport.port == port && !strcmp(dev_name, c->u.ibendport.dev_name)) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_UNLABELED; } out: return rc; } /* * Return the SID of the port specified by * `domain', `type', `protocol', and `port'. */ int hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)), uint16_t type __attribute__ ((unused)), uint8_t protocol, uint16_t port, sepol_security_id_t * out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_PORT]; while (c) { if (c->u.port.protocol == protocol && c->u.port.low_port <= port && c->u.port.high_port >= port) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_PORT; } out: return rc; } /* * Return the SIDs to use for a network interface * with the name `name'. The `if_sid' SID is returned for * the interface and the `msg_sid' SID is returned as * the default SID for messages received on the * interface. */ int hidden sepol_netif_sid(char *name, sepol_security_id_t * if_sid, sepol_security_id_t * msg_sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_NETIF]; while (c) { if (strcmp(name, c->u.name) == 0) break; c = c->next; } if (c) { if (!c->sid[0] || !c->sid[1]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; rc = sepol_sidtab_context_to_sid(sidtab, &c->context[1], &c->sid[1]); if (rc) goto out; } *if_sid = c->sid[0]; *msg_sid = c->sid[1]; } else { *if_sid = SECINITSID_NETIF; *msg_sid = SECINITSID_NETMSG; } out: return rc; } static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr, uint32_t * mask) { int i, fail = 0; for (i = 0; i < 4; i++) if (addr[i] != (input[i] & mask[i])) { fail = 1; break; } return !fail; } /* * Return the SID of the node specified by the address * `addrp' where `addrlen' is the length of the address * in bytes and `domain' is the communications domain or * address family in which the address should be interpreted. */ int hidden sepol_node_sid(uint16_t domain, void *addrp, size_t addrlen, sepol_security_id_t * out_sid) { int rc = 0; ocontext_t *c; switch (domain) { case AF_INET:{ uint32_t addr; if (addrlen != sizeof(uint32_t)) { rc = -EINVAL; goto out; } addr = *((uint32_t *) addrp); c = policydb->ocontexts[OCON_NODE]; while (c) { if (c->u.node.addr == (addr & c->u.node.mask)) break; c = c->next; } break; } case AF_INET6: if (addrlen != sizeof(uint64_t) * 2) { rc = -EINVAL; goto out; } c = policydb->ocontexts[OCON_NODE6]; while (c) { if (match_ipv6_addrmask(addrp, c->u.node6.addr, c->u.node6.mask)) break; c = c->next; } break; default: *out_sid = SECINITSID_NODE; goto out; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_NODE; } out: return rc; } /* * Generate the set of SIDs for legal security contexts * for a given user that can be reached by `fromsid'. * Set `*sids' to point to a dynamically allocated * array containing the set of SIDs. Set `*nel' to the * number of elements in the array. */ #define SIDS_NEL 25 int hidden sepol_get_user_sids(sepol_security_id_t fromsid, char *username, sepol_security_id_t ** sids, uint32_t * nel) { context_struct_t *fromcon, usercon; sepol_security_id_t *mysids, *mysids2, sid; uint32_t mynel = 0, maxnel = SIDS_NEL; user_datum_t *user; role_datum_t *role; struct sepol_av_decision avd; int rc = 0; unsigned int i, j, reason; ebitmap_node_t *rnode, *tnode; fromcon = sepol_sidtab_search(sidtab, fromsid); if (!fromcon) { rc = -EINVAL; goto out; } user = (user_datum_t *) hashtab_search(policydb->p_users.table, username); if (!user) { rc = -EINVAL; goto out; } usercon.user = user->s.value; mysids = malloc(maxnel * sizeof(sepol_security_id_t)); if (!mysids) { rc = -ENOMEM; goto out; } memset(mysids, 0, maxnel * sizeof(sepol_security_id_t)); ebitmap_for_each_bit(&user->roles.roles, rnode, i) { if (!ebitmap_node_get_bit(rnode, i)) continue; role = policydb->role_val_to_struct[i]; usercon.role = i + 1; ebitmap_for_each_bit(&role->types.types, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; usercon.type = j + 1; if (usercon.type == fromcon->type) continue; if (mls_setup_user_range (fromcon, user, &usercon, policydb->mls)) continue; rc = context_struct_compute_av(fromcon, &usercon, SECCLASS_PROCESS, PROCESS__TRANSITION, &avd, &reason, NULL, 0); if (rc || !(avd.allowed & PROCESS__TRANSITION)) continue; rc = sepol_sidtab_context_to_sid(sidtab, &usercon, &sid); if (rc) { free(mysids); goto out; } if (mynel < maxnel) { mysids[mynel++] = sid; } else { maxnel += SIDS_NEL; mysids2 = malloc(maxnel * sizeof(sepol_security_id_t)); if (!mysids2) { rc = -ENOMEM; free(mysids); goto out; } memset(mysids2, 0, maxnel * sizeof(sepol_security_id_t)); memcpy(mysids2, mysids, mynel * sizeof(sepol_security_id_t)); free(mysids); mysids = mysids2; mysids[mynel++] = sid; } } } *sids = mysids; *nel = mynel; out: return rc; } /* * Return the SID to use for a file in a filesystem * that cannot support a persistent label mapping or use another * fixed labeling behavior like transition SIDs or task SIDs. */ int hidden sepol_genfs_sid(const char *fstype, const char *path, sepol_security_class_t sclass, sepol_security_id_t * sid) { size_t len; genfs_t *genfs; ocontext_t *c; int rc = 0, cmp = 0; for (genfs = policydb->genfs; genfs; genfs = genfs->next) { cmp = strcmp(fstype, genfs->fstype); if (cmp <= 0) break; } if (!genfs || cmp) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } for (c = genfs->head; c; c = c->next) { len = strlen(c->u.name); if ((!c->v.sclass || sclass == c->v.sclass) && (strncmp(c->u.name, path, len) == 0)) break; } if (!c) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0]; out: return rc; } int hidden sepol_fs_use(const char *fstype, unsigned int *behavior, sepol_security_id_t * sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_FSUSE]; while (c) { if (strcmp(fstype, c->u.name) == 0) break; c = c->next; } if (c) { *behavior = c->v.behavior; if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0]; } else { rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid); if (rc) { *behavior = SECURITY_FS_USE_NONE; rc = 0; } else { *behavior = SECURITY_FS_USE_GENFS; } } out: return rc; } /* FLASK */ libsepol/src/sidtab.c0100644 0000000 0000000 00000013647 13756670065 013651 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the SID table type. */ #include #include #include #include #include #include #define SIDTAB_HASH(sid) \ (sid & SIDTAB_HASH_MASK) #define INIT_SIDTAB_LOCK(s) #define SIDTAB_LOCK(s) #define SIDTAB_UNLOCK(s) int sepol_sidtab_init(sidtab_t * s) { int i; s->htable = malloc(sizeof(sidtab_ptr_t) * SIDTAB_SIZE); if (!s->htable) return -ENOMEM; for (i = 0; i < SIDTAB_SIZE; i++) s->htable[i] = (sidtab_ptr_t) NULL; s->nel = 0; s->next_sid = 1; s->shutdown = 0; INIT_SIDTAB_LOCK(s); return 0; } int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid, context_struct_t * context) { int hvalue; sidtab_node_t *prev, *cur, *newnode; if (!s || !s->htable) return -ENOMEM; hvalue = SIDTAB_HASH(sid); prev = NULL; cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) { prev = cur; cur = cur->next; } if (cur && sid == cur->sid) { errno = EEXIST; return -EEXIST; } newnode = (sidtab_node_t *) malloc(sizeof(sidtab_node_t)); if (newnode == NULL) return -ENOMEM; newnode->sid = sid; if (context_cpy(&newnode->context, context)) { free(newnode); return -ENOMEM; } if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = s->htable[hvalue]; s->htable[hvalue] = newnode; } s->nel++; if (sid >= s->next_sid) s->next_sid = sid + 1; return 0; } int sepol_sidtab_remove(sidtab_t * s, sepol_security_id_t sid) { int hvalue; sidtab_node_t *cur, *last; if (!s || !s->htable) return -ENOENT; hvalue = SIDTAB_HASH(sid); last = NULL; cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) { last = cur; cur = cur->next; } if (cur == NULL || sid != cur->sid) return -ENOENT; if (last == NULL) s->htable[hvalue] = cur->next; else last->next = cur->next; context_destroy(&cur->context); free(cur); s->nel--; return 0; } context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid) { int hvalue; sidtab_node_t *cur; if (!s || !s->htable) return NULL; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) cur = cur->next; if (cur == NULL || sid != cur->sid) { /* Remap invalid SIDs to the unlabeled SID. */ sid = SECINITSID_UNLABELED; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) cur = cur->next; if (!cur || sid != cur->sid) return NULL; } return &cur->context; } int sepol_sidtab_map(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args) { int i, ret; sidtab_node_t *cur; if (!s || !s->htable) return 0; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { ret = apply(cur->sid, &cur->context, args); if (ret) return ret; cur = cur->next; } } return 0; } void sepol_sidtab_map_remove_on_error(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args) { int i, ret; sidtab_node_t *last, *cur, *temp; if (!s || !s->htable) return; for (i = 0; i < SIDTAB_SIZE; i++) { last = NULL; cur = s->htable[i]; while (cur != NULL) { ret = apply(cur->sid, &cur->context, args); if (ret) { if (last) { last->next = cur->next; } else { s->htable[i] = cur->next; } temp = cur; cur = cur->next; context_destroy(&temp->context); free(temp); s->nel--; } else { last = cur; cur = cur->next; } } } return; } static inline sepol_security_id_t sepol_sidtab_search_context(sidtab_t * s, context_struct_t * context) { int i; sidtab_node_t *cur; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { if (context_cmp(&cur->context, context)) return cur->sid; cur = cur->next; } } return 0; } int sepol_sidtab_context_to_sid(sidtab_t * s, context_struct_t * context, sepol_security_id_t * out_sid) { sepol_security_id_t sid; int ret = 0; *out_sid = SEPOL_SECSID_NULL; sid = sepol_sidtab_search_context(s, context); if (!sid) { SIDTAB_LOCK(s); /* Rescan now that we hold the lock. */ sid = sepol_sidtab_search_context(s, context); if (sid) goto unlock_out; /* No SID exists for the context. Allocate a new one. */ if (s->next_sid == UINT_MAX || s->shutdown) { ret = -ENOMEM; goto unlock_out; } sid = s->next_sid++; ret = sepol_sidtab_insert(s, sid, context); if (ret) s->next_sid--; unlock_out: SIDTAB_UNLOCK(s); } if (ret) return ret; *out_sid = sid; return 0; } void sepol_sidtab_hash_eval(sidtab_t * h, char *tag) { int i, chain_len, slots_used, max_chain_len; sidtab_node_t *cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < SIDTAB_SIZE; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len); } void sepol_sidtab_destroy(sidtab_t * s) { int i; sidtab_ptr_t cur, temp; if (!s || !s->htable) return; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; context_destroy(&temp->context); free(temp); } s->htable[i] = NULL; } free(s->htable); s->htable = NULL; s->nel = 0; s->next_sid = 1; } void sepol_sidtab_set(sidtab_t * dst, sidtab_t * src) { SIDTAB_LOCK(src); dst->htable = src->htable; dst->nel = src->nel; dst->next_sid = src->next_sid; dst->shutdown = 0; SIDTAB_UNLOCK(src); } void sepol_sidtab_shutdown(sidtab_t * s) { SIDTAB_LOCK(s); s->shutdown = 1; SIDTAB_UNLOCK(s); } /* FLASK */ libsepol/src/symtab.c0100644 0000000 0000000 00000001730 13756670065 013670 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the symbol table type. */ #include #include #include static unsigned int symhash(hashtab_t h, const_hashtab_key_t key) { const char *p, *keyp; size_t size; unsigned int val; val = 0; keyp = (const char *)key; size = strlen(keyp); for (p = keyp; ((size_t) (p - keyp)) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (h->size - 1); } static int symcmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { return strcmp(key1, key2); } int symtab_init(symtab_t * s, unsigned int size) { s->table = hashtab_create(symhash, symcmp, size); if (!s->table) return -1; s->nprim = 0; return 0; } void symtab_destroy(symtab_t * s) { if (!s) return; if (s->table) hashtab_destroy(s->table); return; } /* FLASK */ libsepol/src/user_internal.h0100644 0000000 0000000 00000001145 13756670065 015250 0ustar000000000 0000000 #ifndef _SEPOL_USER_INTERNAL_H_ #define _SEPOL_USER_INTERNAL_H_ #include #include #include "dso.h" hidden_proto(sepol_user_add_role) hidden_proto(sepol_user_create) hidden_proto(sepol_user_free) hidden_proto(sepol_user_get_mlslevel) hidden_proto(sepol_user_get_mlsrange) hidden_proto(sepol_user_get_roles) hidden_proto(sepol_user_has_role) hidden_proto(sepol_user_key_create) hidden_proto(sepol_user_key_unpack) hidden_proto(sepol_user_set_mlslevel) hidden_proto(sepol_user_set_mlsrange) hidden_proto(sepol_user_set_name) #endif libsepol/src/user_record.c0100644 0000000 0000000 00000016771 13756670065 014720 0ustar000000000 0000000 #include #include #include #include "user_internal.h" #include "debug.h" struct sepol_user { /* This user's name */ char *name; /* This user's mls level (only required for mls) */ char *mls_level; /* This user's mls range (only required for mls) */ char *mls_range; /* The role array */ char **roles; /* The number of roles */ unsigned int num_roles; }; struct sepol_user_key { /* This user's name */ char *name; }; int sepol_user_key_create(sepol_handle_t * handle, const char *name, sepol_user_key_t ** key_ptr) { sepol_user_key_t *tmp_key = (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t)); if (!tmp_key) { ERR(handle, "out of memory, " "could not create selinux user key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, could not create selinux user key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } hidden_def(sepol_user_key_create) void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name) { *name = key->name; } hidden_def(sepol_user_key_unpack) int sepol_user_key_extract(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_key_t ** key_ptr) { if (sepol_user_key_create(handle, user->name, key_ptr) < 0) { ERR(handle, "could not extract key from user %s", user->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_user_key_free(sepol_user_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key) { return strcmp(user->name, key->name); } int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2) { return strcmp(user->name, user2->name); } /* Name */ const char *sepol_user_get_name(const sepol_user_t * user) { return user->name; } int sepol_user_set_name(sepol_handle_t * handle, sepol_user_t * user, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set name"); return STATUS_ERR; } free(user->name); user->name = tmp_name; return STATUS_SUCCESS; } hidden_def(sepol_user_set_name) /* MLS */ const char *sepol_user_get_mlslevel(const sepol_user_t * user) { return user->mls_level; } hidden_def(sepol_user_get_mlslevel) int sepol_user_set_mlslevel(sepol_handle_t * handle, sepol_user_t * user, const char *mls_level) { char *tmp_mls_level = strdup(mls_level); if (!tmp_mls_level) { ERR(handle, "out of memory, " "could not set MLS default level"); return STATUS_ERR; } free(user->mls_level); user->mls_level = tmp_mls_level; return STATUS_SUCCESS; } hidden_def(sepol_user_set_mlslevel) const char *sepol_user_get_mlsrange(const sepol_user_t * user) { return user->mls_range; } hidden_def(sepol_user_get_mlsrange) int sepol_user_set_mlsrange(sepol_handle_t * handle, sepol_user_t * user, const char *mls_range) { char *tmp_mls_range = strdup(mls_range); if (!tmp_mls_range) { ERR(handle, "out of memory, " "could not set MLS allowed range"); return STATUS_ERR; } free(user->mls_range); user->mls_range = tmp_mls_range; return STATUS_SUCCESS; } hidden_def(sepol_user_set_mlsrange) /* Roles */ int sepol_user_get_num_roles(const sepol_user_t * user) { return user->num_roles; } int sepol_user_add_role(sepol_handle_t * handle, sepol_user_t * user, const char *role) { char *role_cp; char **roles_realloc = NULL; if (sepol_user_has_role(user, role)) return STATUS_SUCCESS; role_cp = strdup(role); if (!role_cp) goto omem; roles_realloc = realloc(user->roles, sizeof(char *) * (user->num_roles + 1)); if (!roles_realloc) goto omem; user->num_roles++; user->roles = roles_realloc; user->roles[user->num_roles - 1] = role_cp; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not add role %s", role); free(role_cp); free(roles_realloc); return STATUS_ERR; } hidden_def(sepol_user_add_role) int sepol_user_has_role(const sepol_user_t * user, const char *role) { unsigned int i; for (i = 0; i < user->num_roles; i++) if (!strcmp(user->roles[i], role)) return 1; return 0; } hidden_def(sepol_user_has_role) int sepol_user_set_roles(sepol_handle_t * handle, sepol_user_t * user, const char **roles_arr, unsigned int num_roles) { unsigned int i; char **tmp_roles = NULL; if (num_roles > 0) { /* First, make a copy */ tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles); if (!tmp_roles) goto omem; for (i = 0; i < num_roles; i++) { tmp_roles[i] = strdup(roles_arr[i]); if (!tmp_roles[i]) goto omem; } } /* Apply other changes */ for (i = 0; i < user->num_roles; i++) free(user->roles[i]); free(user->roles); user->roles = tmp_roles; user->num_roles = num_roles; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not allocate roles array for" "user %s", user->name); if (tmp_roles) { for (i = 0; i < num_roles; i++) { if (!tmp_roles[i]) break; free(tmp_roles[i]); } } free(tmp_roles); return STATUS_ERR; } int sepol_user_get_roles(sepol_handle_t * handle, const sepol_user_t * user, const char ***roles_arr, unsigned int *num_roles) { unsigned int i; const char **tmp_roles = (const char **)malloc(sizeof(char *) * user->num_roles); if (!tmp_roles) goto omem; for (i = 0; i < user->num_roles; i++) tmp_roles[i] = user->roles[i]; *roles_arr = tmp_roles; *num_roles = user->num_roles; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not " "allocate roles array for user %s", user->name); free(tmp_roles); return STATUS_ERR; } hidden_def(sepol_user_get_roles) void sepol_user_del_role(sepol_user_t * user, const char *role) { unsigned int i; for (i = 0; i < user->num_roles; i++) { if (!strcmp(user->roles[i], role)) { free(user->roles[i]); user->roles[i] = NULL; user->roles[i] = user->roles[user->num_roles - 1]; user->num_roles--; } } } /* Create */ int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr) { sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t)); if (!user) { ERR(handle, "out of memory, " "could not create selinux user record"); return STATUS_ERR; } user->roles = NULL; user->num_roles = 0; user->name = NULL; user->mls_level = NULL; user->mls_range = NULL; *user_ptr = user; return STATUS_SUCCESS; } hidden_def(sepol_user_create) /* Deep copy clone */ int sepol_user_clone(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_t ** user_ptr) { sepol_user_t *new_user = NULL; unsigned int i; if (sepol_user_create(handle, &new_user) < 0) goto err; if (sepol_user_set_name(handle, new_user, user->name) < 0) goto err; for (i = 0; i < user->num_roles; i++) { if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0) goto err; } if (user->mls_level && (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0)) goto err; if (user->mls_range && (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0)) goto err; *user_ptr = new_user; return STATUS_SUCCESS; err: ERR(handle, "could not clone selinux user record"); sepol_user_free(new_user); return STATUS_ERR; } /* Destroy */ void sepol_user_free(sepol_user_t * user) { unsigned int i; if (!user) return; free(user->name); for (i = 0; i < user->num_roles; i++) free(user->roles[i]); free(user->roles); free(user->mls_level); free(user->mls_range); free(user); } hidden_def(sepol_user_free) libsepol/src/users.c0100644 0000000 0000000 00000021231 13756670065 013530 0ustar000000000 0000000 #include #include #include #include "private.h" #include "debug.h" #include "handle.h" #include #include #include #include "user_internal.h" #include "mls.h" static int user_to_record(sepol_handle_t * handle, const policydb_t * policydb, int user_idx, sepol_user_t ** record) { const char *name = policydb->p_user_val_to_name[user_idx]; user_datum_t *usrdatum = policydb->user_val_to_struct[user_idx]; ebitmap_t *roles; ebitmap_node_t *rnode; unsigned bit; sepol_user_t *tmp_record = NULL; if (!usrdatum) goto err; roles = &(usrdatum->roles.roles); if (sepol_user_create(handle, &tmp_record) < 0) goto err; if (sepol_user_set_name(handle, tmp_record, name) < 0) goto err; /* Extract roles */ ebitmap_for_each_bit(roles, rnode, bit) { if (ebitmap_node_get_bit(rnode, bit)) { char *role = policydb->p_role_val_to_name[bit]; if (sepol_user_add_role(handle, tmp_record, role) < 0) goto err; } } /* Extract MLS info */ if (policydb->mls) { context_struct_t context; char *str; context_init(&context); if (mls_level_cpy(&context.range.level[0], &usrdatum->exp_dfltlevel) < 0) { ERR(handle, "could not copy MLS level"); context_destroy(&context); goto err; } if (mls_level_cpy(&context.range.level[1], &usrdatum->exp_dfltlevel) < 0) { ERR(handle, "could not copy MLS level"); context_destroy(&context); goto err; } if (mls_to_string(handle, policydb, &context, &str) < 0) { context_destroy(&context); goto err; } context_destroy(&context); if (sepol_user_set_mlslevel(handle, tmp_record, str) < 0) { free(str); goto err; } free(str); context_init(&context); if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) { ERR(handle, "could not copy MLS range"); context_destroy(&context); goto err; } if (mls_to_string(handle, policydb, &context, &str) < 0) { context_destroy(&context); goto err; } context_destroy(&context); if (sepol_user_set_mlsrange(handle, tmp_record, str) < 0) { free(str); goto err; } free(str); } *record = tmp_record; return STATUS_SUCCESS; err: /* FIXME: handle error */ sepol_user_free(tmp_record); return STATUS_ERR; } int sepol_user_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_user_key_t * key, const sepol_user_t * user) { policydb_t *policydb = &p->p; /* For user data */ const char *cname, *cmls_level, *cmls_range; char *name = NULL; const char **roles = NULL; unsigned int num_roles = 0; /* Low-level representation */ user_datum_t *usrdatum = NULL; role_datum_t *roldatum; unsigned int i; context_struct_t context; unsigned bit; int new = 0; ebitmap_node_t *rnode; /* First, extract all the data */ sepol_user_key_unpack(key, &cname); cmls_level = sepol_user_get_mlslevel(user); cmls_range = sepol_user_get_mlsrange(user); /* Make sure that worked properly */ if (sepol_user_get_roles(handle, user, &roles, &num_roles) < 0) goto err; /* Now, see if a user exists */ usrdatum = hashtab_search(policydb->p_users.table, cname); /* If it does, we will modify it */ if (usrdatum) { int value_cp = usrdatum->s.value; user_datum_destroy(usrdatum); user_datum_init(usrdatum); usrdatum->s.value = value_cp; /* Otherwise, create a new one */ } else { usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t)); if (!usrdatum) goto omem; user_datum_init(usrdatum); new = 1; } /* For every role */ for (i = 0; i < num_roles; i++) { /* Search for the role */ roldatum = hashtab_search(policydb->p_roles.table, roles[i]); if (!roldatum) { ERR(handle, "undefined role %s for user %s", roles[i], cname); goto err; } /* Set the role and every role it dominates */ ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) { if (ebitmap_node_get_bit(rnode, bit)) { if (ebitmap_set_bit (&(usrdatum->roles.roles), bit, 1)) goto omem; } } } /* For MLS systems */ if (policydb->mls) { /* MLS level */ if (cmls_level == NULL) { ERR(handle, "MLS is enabled, but no MLS " "default level was defined for user %s", cname); goto err; } context_init(&context); if (mls_from_string(handle, policydb, cmls_level, &context) < 0) { context_destroy(&context); goto err; } if (mls_level_cpy(&usrdatum->exp_dfltlevel, &context.range.level[0]) < 0) { ERR(handle, "could not copy MLS level %s", cmls_level); context_destroy(&context); goto err; } context_destroy(&context); /* MLS range */ if (cmls_range == NULL) { ERR(handle, "MLS is enabled, but no MLS" "range was defined for user %s", cname); goto err; } context_init(&context); if (mls_from_string(handle, policydb, cmls_range, &context) < 0) { context_destroy(&context); goto err; } if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) { ERR(handle, "could not copy MLS range %s", cmls_range); context_destroy(&context); goto err; } context_destroy(&context); } else if (cmls_level != NULL || cmls_range != NULL) { ERR(handle, "MLS is disabled, but MLS level/range " "was found for user %s", cname); goto err; } /* If there are no errors, and this is a new user, add the user to policy */ if (new) { void *tmp_ptr; /* Ensure reverse lookup array has enough space */ tmp_ptr = realloc(policydb->user_val_to_struct, (policydb->p_users.nprim + 1) * sizeof(user_datum_t *)); if (!tmp_ptr) goto omem; policydb->user_val_to_struct = tmp_ptr; policydb->user_val_to_struct[policydb->p_users.nprim] = NULL; tmp_ptr = realloc(policydb->sym_val_to_name[SYM_USERS], (policydb->p_users.nprim + 1) * sizeof(char *)); if (!tmp_ptr) goto omem; policydb->sym_val_to_name[SYM_USERS] = tmp_ptr; policydb->p_user_val_to_name[policydb->p_users.nprim] = NULL; /* Need to copy the user name */ name = strdup(cname); if (!name) goto omem; /* Store user */ usrdatum->s.value = ++policydb->p_users.nprim; if (hashtab_insert(policydb->p_users.table, name, (hashtab_datum_t) usrdatum) < 0) goto omem; /* Set up reverse entry */ policydb->p_user_val_to_name[usrdatum->s.value - 1] = name; policydb->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; name = NULL; /* Expand roles */ if (role_set_expand(&usrdatum->roles, &usrdatum->cache, policydb, NULL, NULL)) { ERR(handle, "unable to expand role set"); goto err; } } free(roles); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not load %s into policy", name); free(name); free(roles); if (new && usrdatum) { role_set_destroy(&usrdatum->roles); free(usrdatum); } return STATUS_ERR; } int sepol_user_exists(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, const sepol_user_key_t * key, int *response) { const policydb_t *policydb = &p->p; const char *cname; sepol_user_key_unpack(key, &cname); *response = (hashtab_search(policydb->p_users.table, cname) != NULL); return STATUS_SUCCESS; } int sepol_user_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { const policydb_t *policydb = &p->p; *response = policydb->p_users.nprim; return STATUS_SUCCESS; } int sepol_user_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_user_key_t * key, sepol_user_t ** response) { const policydb_t *policydb = &p->p; user_datum_t *usrdatum = NULL; const char *cname; sepol_user_key_unpack(key, &cname); usrdatum = hashtab_search(policydb->p_users.table, cname); if (!usrdatum) { *response = NULL; return STATUS_SUCCESS; } if (user_to_record(handle, policydb, usrdatum->s.value - 1, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not query user %s", cname); return STATUS_ERR; } int sepol_user_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_user_t * user, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; unsigned int nusers = policydb->p_users.nprim; sepol_user_t *user = NULL; unsigned int i; /* For each user */ for (i = 0; i < nusers; i++) { int status; if (user_to_record(handle, policydb, i, &user) < 0) goto err; /* Invoke handler */ status = fn(user, arg); if (status < 0) goto err; sepol_user_free(user); user = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over users"); sepol_user_free(user); return STATUS_ERR; } libsepol/src/util.c0100644 0000000 0000000 00000016261 13756670065 013353 0ustar000000000 0000000 /* Authors: Joshua Brindle * Jason Tang * * Copyright (C) 2005-2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include struct val_to_name { unsigned int val; char *name; }; /* Add an unsigned integer to a dynamically reallocated array. *cnt * is a reference pointer to the number of values already within array * *a; it will be incremented upon successfully appending i. If *a is * NULL then this function will create a new array (*cnt is reset to * 0). Return 0 on success, -1 on out of memory. */ int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a) { if (cnt == NULL || a == NULL) return -1; /* FIX ME: This is not very elegant! We use an array that we * grow as new uint32_t are added to an array. But rather * than be smart about it, for now we realloc() the array each * time a new uint32_t is added! */ if (*a != NULL) *a = (uint32_t *) realloc(*a, (*cnt + 1) * sizeof(uint32_t)); else { /* empty list */ *cnt = 0; *a = (uint32_t *) malloc(sizeof(uint32_t)); } if (*a == NULL) { return -1; } (*a)[*cnt] = i; (*cnt)++; return 0; } static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data) { struct val_to_name *v = data; perm_datum_t *perdatum; perdatum = (perm_datum_t *) datum; if (v->val == perdatum->s.value) { v->name = key; return 1; } return 0; } char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, sepol_access_vector_t av) { struct val_to_name v; static char avbuf[1024]; class_datum_t *cladatum; char *perm = NULL, *p; unsigned int i; int rc; int avlen = 0, len; memset(avbuf, 0, sizeof avbuf); cladatum = policydbp->class_val_to_struct[tclass - 1]; p = avbuf; for (i = 0; i < cladatum->permissions.nprim; i++) { if (av & (1 << i)) { v.val = i + 1; rc = hashtab_map(cladatum->permissions.table, perm_name, &v); if (!rc && cladatum->comdatum) { rc = hashtab_map(cladatum->comdatum-> permissions.table, perm_name, &v); } if (rc) perm = v.name; if (perm) { len = snprintf(p, sizeof(avbuf) - avlen, " %s", perm); if (len < 0 || (size_t) len >= (sizeof(avbuf) - avlen)) return NULL; p += len; avlen += len; } } } return avbuf; } #define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; unsigned int in_range = 0; static char xpermsbuf[2048]; xpermsbuf[0] = '\0'; char *p; int len, xpermslen = 0; p = xpermsbuf; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) return NULL; len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "ioctl { "); p += len; xpermslen += len; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, value); } else { len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx ", value); } } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); } else { len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); } } if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) return NULL; p += len; xpermslen += len; if (in_range) in_range = 0; } len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "}"); if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) return NULL; return xpermsbuf; } /* * The tokenize and tokenize_str functions may be used to * replace sscanf to read tokens from buffers. */ /* Read a token from a buffer */ static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len) { char *tmp_buf = *ptr; *str = NULL; while (**ptr != '\0') { if (isspace(delim) && isspace(**ptr)) { (*ptr)++; break; } else if (!isspace(delim) && **ptr == delim) { (*ptr)++; break; } (*ptr)++; } *len = *ptr - tmp_buf; /* If the end of the string has not been reached, this will ensure the * delimiter is not included when returning the token. */ if (**ptr != '\0') { (*len)--; } *str = strndup(tmp_buf, *len); if (!*str) { return -1; } /* Squash spaces if the delimiter is a whitespace character */ while (**ptr != '\0' && isspace(delim) && isspace(**ptr)) { (*ptr)++; } return 0; } /* * line_buf - Buffer containing string to tokenize. * delim - The delimiter used to tokenize line_buf. A whitespace delimiter will * be tokenized using isspace(). * num_args - The number of parameter entries to process. * ... - A 'char **' for each parameter. * returns - The number of items processed. * * This function calls tokenize_str() to do the actual string processing. The * caller is responsible for calling free() on each additional argument. The * function will not tokenize more than num_args and the last argument will * contain the remaining content of line_buf. If the delimiter is any whitespace * character, then all whitespace will be squashed. */ int hidden tokenize(char *line_buf, char delim, int num_args, ...) { char **arg, *buf_p; int rc, items; size_t arg_len = 0; va_list ap; buf_p = line_buf; /* Process the arguments */ va_start(ap, num_args); for (items = 0; items < num_args && *buf_p != '\0'; items++) { arg = va_arg(ap, char **); /* Save the remainder of the string in arg */ if (items == num_args - 1) { *arg = strdup(buf_p); if (*arg == NULL) { goto exit; } continue; } rc = tokenize_str(delim, arg, &buf_p, &arg_len); if (rc < 0) { goto exit; } } exit: va_end(ap); return items; } libsepol/src/write.c0100644 0000000 0000000 00000167026 13756670065 013536 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Joshua Brindle and Jason Tang * * Module writing support * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003-2005 Tresys Technology, LLC * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" #include "mls.h" struct policy_data { struct policy_file *fp; struct policydb *p; }; static int avrule_write_list(policydb_t *p, avrule_t * avrules, struct policy_file *fp); static int ebitmap_write(ebitmap_t * e, struct policy_file *fp) { ebitmap_node_t *n; uint32_t buf[32], bit, count; uint64_t map; size_t items; buf[0] = cpu_to_le32(MAPSIZE); buf[1] = cpu_to_le32(e->highbit); count = 0; for (n = e->node; n; n = n->next) count++; buf[2] = cpu_to_le32(count); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; for (n = e->node; n; n = n->next) { bit = cpu_to_le32(n->startbit); items = put_entry(&bit, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; map = cpu_to_le64(n->map); items = put_entry(&map, sizeof(uint64_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* Ordering of datums in the original avtab format in the policy file. */ static uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, AVTAB_AUDITALLOW, AVTAB_TRANSITION, AVTAB_CHANGE, AVTAB_MEMBER }; static int avtab_write_item(policydb_t * p, avtab_ptr_t cur, struct policy_file *fp, unsigned merge, unsigned commit, uint32_t * nel) { avtab_ptr_t node; uint8_t buf8; uint16_t buf16[4]; uint32_t buf32[10], lookup, val; size_t items, items2; unsigned set; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); unsigned int i; if (oldvers) { /* Generate the old avtab format. Requires merging similar entries if uncond avtab. */ if (merge) { if (cur->merged) return POLICYDB_SUCCESS; /* already merged by prior merge */ } items = 1; /* item 0 is used for the item count */ val = cur->key.source_type; buf32[items++] = cpu_to_le32(val); val = cur->key.target_type; buf32[items++] = cpu_to_le32(val); val = cur->key.target_class; buf32[items++] = cpu_to_le32(val); val = cur->key.specified & ~AVTAB_ENABLED; if (cur->key.specified & AVTAB_ENABLED) val |= AVTAB_ENABLED_OLD; set = 1; if (merge) { /* Merge specifier values for all similar (av or type) entries that have the same key. */ if (val & AVTAB_AV) lookup = AVTAB_AV; else if (val & AVTAB_TYPE) lookup = AVTAB_TYPE; else return POLICYDB_ERROR; for (node = avtab_search_node_next(cur, lookup); node; node = avtab_search_node_next(node, lookup)) { val |= (node->key.specified & ~AVTAB_ENABLED); set++; if (node->key.specified & AVTAB_ENABLED) val |= AVTAB_ENABLED_OLD; } } if (!(val & (AVTAB_AV | AVTAB_TYPE))) { ERR(fp->handle, "null entry"); return POLICYDB_ERROR; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { ERR(fp->handle, "entry has both access " "vectors and types"); return POLICYDB_ERROR; } buf32[items++] = cpu_to_le32(val); if (merge) { /* Include datums for all similar (av or type) entries that have the same key. */ for (i = 0; i < (sizeof(spec_order) / sizeof(spec_order[0])); i++) { if (val & spec_order[i]) { if (cur->key.specified & spec_order[i]) node = cur; else { node = avtab_search_node_next(cur, spec_order [i]); if (nel) (*nel)--; /* one less node */ } if (!node) { ERR(fp->handle, "missing node"); return POLICYDB_ERROR; } buf32[items++] = cpu_to_le32(node->datum.data); set--; node->merged = 1; } } } else { buf32[items++] = cpu_to_le32(cur->datum.data); cur->merged = 1; set--; } if (set) { ERR(fp->handle, "data count wrong"); return POLICYDB_ERROR; } buf32[0] = cpu_to_le32(items - 1); if (commit) { /* Commit this item to the policy file. */ items2 = put_entry(buf32, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* Generate the new avtab format. */ buf16[0] = cpu_to_le16(cur->key.source_type); buf16[1] = cpu_to_le16(cur->key.target_type); buf16[2] = cpu_to_le16(cur->key.target_class); buf16[3] = cpu_to_le16(cur->key.specified); items = put_entry(buf16, sizeof(uint16_t), 4, fp); if (items != 4) return POLICYDB_ERROR; if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) && (cur->key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "policy version %u does not support ioctl extended" "permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } if (p->target_platform != SEPOL_TARGET_SELINUX && (cur->key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "Target platform %s does not support ioctl " "extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; } if (cur->key.specified & AVTAB_XPERMS) { buf8 = cur->datum.xperms->specified; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; buf8 = cur->datum.xperms->driver; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++) buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]); items = put_entry(buf32, sizeof(uint32_t),8,fp); if (items != 8) return POLICYDB_ERROR; } else { buf32[0] = cpu_to_le32(cur->datum.data); items = put_entry(buf32, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static inline void avtab_reset_merged(avtab_t * a) { unsigned int i; avtab_ptr_t cur; for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) cur->merged = 0; } } static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp) { unsigned int i; int rc; avtab_t expa; avtab_ptr_t cur; uint32_t nel; size_t items; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); if (oldvers) { /* Old avtab format. First, we need to expand attributes. Then, we need to merge similar entries, so we need to track merged nodes and compute the final nel. */ if (avtab_init(&expa)) return POLICYDB_ERROR; if (expand_avtab(p, a, &expa)) { rc = -1; goto out; } a = &expa; avtab_reset_merged(a); nel = a->nel; } else { /* New avtab format. nel is good to go. */ nel = cpu_to_le32(a->nel); items = put_entry(&nel, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { /* If old format, compute final nel. If new format, write out the items. */ if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) { rc = -1; goto out; } } } if (oldvers) { /* Old avtab format. Write the computed nel value, then write the items. */ nel = cpu_to_le32(nel); items = put_entry(&nel, sizeof(uint32_t), 1, fp); if (items != 1) { rc = -1; goto out; } avtab_reset_merged(a); for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { if (avtab_write_item(p, cur, fp, 1, 1, NULL)) { rc = -1; goto out; } } } } rc = 0; out: if (oldvers) avtab_destroy(&expa); return rc; } /* * Write a semantic MLS level structure to a policydb binary * representation file. */ static int mls_write_semantic_level_helper(mls_semantic_level_t * l, struct policy_file *fp) { uint32_t buf[2], ncat = 0; size_t items; mls_semantic_cat_t *cat; for (cat = l->cat; cat; cat = cat->next) ncat++; buf[0] = cpu_to_le32(l->sens); buf[1] = cpu_to_le32(ncat); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; for (cat = l->cat; cat; cat = cat->next) { buf[0] = cpu_to_le32(cat->low); buf[1] = cpu_to_le32(cat->high); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * Read a semantic MLS range structure to a policydb binary * representation file. */ static int mls_write_semantic_range_helper(mls_semantic_range_t * r, struct policy_file *fp) { int rc; rc = mls_write_semantic_level_helper(&r->level[0], fp); if (rc) return rc; rc = mls_write_semantic_level_helper(&r->level[1], fp); return rc; } /* * Write a MLS level structure to a policydb binary * representation file. */ static int mls_write_level(mls_level_t * l, struct policy_file *fp) { uint32_t sens; size_t items; sens = cpu_to_le32(l->sens); items = put_entry(&sens, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (ebitmap_write(&l->cat, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } /* * Write a MLS range structure to a policydb binary * representation file. */ static int mls_write_range_helper(mls_range_t * r, struct policy_file *fp) { uint32_t buf[3]; size_t items, items2; int eq; eq = mls_level_eq(&r->level[1], &r->level[0]); items = 1; /* item 0 is used for the item count */ buf[items++] = cpu_to_le32(r->level[0].sens); if (!eq) buf[items++] = cpu_to_le32(r->level[1].sens); buf[0] = cpu_to_le32(items - 1); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if (ebitmap_write(&r->level[0].cat, fp)) return POLICYDB_ERROR; if (!eq) if (ebitmap_write(&r->level[1].cat, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { level_datum_t *levdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; levdatum = (level_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(levdatum->isalias); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (mls_write_level(levdatum->level, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { cat_datum_t *catdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; catdatum = (cat_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(catdatum->s.value); buf[items++] = cpu_to_le32(catdatum->isalias); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int role_trans_write(policydb_t *p, struct policy_file *fp) { role_trans_t *r = p->role_tr; role_trans_t *tr; uint32_t buf[3]; size_t nel, items; int new_roletr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_ROLETRANS); int warning_issued = 0; nel = 0; for (tr = r; tr; tr = tr->next) if(new_roletr || tr->tclass == SECCLASS_PROCESS) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (tr = r; tr; tr = tr->next) { if (!new_roletr && tr->tclass != SECCLASS_PROCESS) { if (!warning_issued) WARN(fp->handle, "Discarding role_transition " "rules for security classes other than " "\"process\""); warning_issued = 1; continue; } buf[0] = cpu_to_le32(tr->role); buf[1] = cpu_to_le32(tr->type); buf[2] = cpu_to_le32(tr->new_role); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; if (new_roletr) { buf[0] = cpu_to_le32(tr->tclass); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int role_allow_write(role_allow_t * r, struct policy_file *fp) { role_allow_t *ra; uint32_t buf[2]; size_t nel, items; nel = 0; for (ra = r; ra; ra = ra->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ra = r; ra; ra = ra->next) { buf[0] = cpu_to_le32(ra->role); buf[1] = cpu_to_le32(ra->new_role); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int filename_write_helper(hashtab_key_t key, void *data, void *ptr) { uint32_t buf[4]; size_t items, len; struct filename_trans *ft = (struct filename_trans *)key; struct filename_trans_datum *otype = data; void *fp = ptr; len = strlen(ft->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(ft->name, sizeof(char), len, fp); if (items != len) return POLICYDB_ERROR; buf[0] = cpu_to_le32(ft->stype); buf[1] = cpu_to_le32(ft->ttype); buf[2] = cpu_to_le32(ft->tclass); buf[3] = cpu_to_le32(otype->otype); items = put_entry(buf, sizeof(uint32_t), 4, fp); if (items != 4) return POLICYDB_ERROR; return 0; } static int filename_trans_write(struct policydb *p, void *fp) { size_t nel, items; uint32_t buf[1]; int rc; if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) return 0; nel = p->filename_trans->nel; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; rc = hashtab_map(p->filename_trans, filename_write_helper, fp); if (rc) return rc; return 0; } static int role_set_write(role_set_t * x, struct policy_file *fp) { size_t items; uint32_t buf[1]; if (ebitmap_write(&x->roles, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(x->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int type_set_write(type_set_t * x, struct policy_file *fp) { size_t items; uint32_t buf[1]; if (ebitmap_write(&x->types, fp)) return POLICYDB_ERROR; if (ebitmap_write(&x->negset, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(x->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { cond_bool_datum_t *booldatum; uint32_t buf[3], len; unsigned int items, items2; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; booldatum = (cond_bool_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(booldatum->s.value); buf[items++] = cpu_to_le32(booldatum->state); buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { buf[0] = cpu_to_le32(booldatum->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * cond_write_cond_av_list doesn't write out the av_list nodes. * Instead it writes out the key/value pairs from the avtab. This * is necessary because there is no way to uniquely identifying rules * in the avtab so it is not possible to associate individual rules * in the avtab with a conditional without saving them as part of * the conditional. This means that the avtab with the conditional * rules will not be saved but will be rebuilt on policy load. */ static int cond_write_av_list(policydb_t * p, cond_av_list_t * list, struct policy_file *fp) { uint32_t buf[4]; cond_av_list_t *cur_list, *new_list = NULL; avtab_t expa; uint32_t len, items; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); int rc = -1; if (oldvers) { if (avtab_init(&expa)) return POLICYDB_ERROR; if (expand_cond_av_list(p, list, &new_list, &expa)) goto out; list = new_list; } len = 0; for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { if (cur_list->node->parse_context) len++; } buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) goto out; if (len == 0) { rc = 0; goto out; } for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { if (cur_list->node->parse_context) if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL)) goto out; } rc = 0; out: if (oldvers) { cond_av_list_destroy(new_list); avtab_destroy(&expa); } return rc; } static int cond_write_node(policydb_t * p, cond_node_t * node, struct policy_file *fp) { cond_expr_t *cur_expr; uint32_t buf[2]; uint32_t items, items2, len; buf[0] = cpu_to_le32(node->cur_state); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; /* expr */ len = 0; for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) len++; buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { items = 0; buf[items++] = cpu_to_le32(cur_expr->expr_type); buf[items++] = cpu_to_le32(cur_expr->bool); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; } if (p->policy_type == POLICY_KERN) { if (cond_write_av_list(p, node->true_list, fp) != 0) return POLICYDB_ERROR; if (cond_write_av_list(p, node->false_list, fp) != 0) return POLICYDB_ERROR; } else { if (avrule_write_list(p, node->avtrue_list, fp)) return POLICYDB_ERROR; if (avrule_write_list(p, node->avfalse_list, fp)) return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { buf[0] = cpu_to_le32(node->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int cond_write_list(policydb_t * p, cond_list_t * list, struct policy_file *fp) { cond_node_t *cur; uint32_t len, items; uint32_t buf[1]; len = 0; for (cur = list; cur != NULL; cur = cur->next) len++; buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (cur = list; cur != NULL; cur = cur->next) { if (cond_write_node(p, cur, fp) != 0) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * Write a security context structure * to a policydb binary representation file. */ static int context_write(struct policydb *p, context_struct_t * c, struct policy_file *fp) { uint32_t buf[32]; size_t items, items2; items = 0; buf[items++] = cpu_to_le32(c->user); buf[items++] = cpu_to_le32(c->role); buf[items++] = cpu_to_le32(c->type); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_BASE)) if (mls_write_range_helper(&c->range, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } /* * The following *_write functions are used to * write the symbol data to a policy database * binary representation file. */ static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { perm_datum_t *perdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; perdatum = (perm_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(perdatum->s.value); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { common_datum_t *comdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; comdatum = (common_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(comdatum->s.value); buf[items++] = cpu_to_le32(comdatum->permissions.nprim); buf[items++] = cpu_to_le32(comdatum->permissions.table->nel); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (hashtab_map(comdatum->permissions.table, perm_write, pd)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int write_cons_helper(policydb_t * p, constraint_node_t * node, int allowxtarget, struct policy_file *fp) { constraint_node_t *c; constraint_expr_t *e; uint32_t buf[3], nexpr; int items; for (c = node; c; c = c->next) { nexpr = 0; for (e = c->expr; e; e = e->next) { nexpr++; } buf[0] = cpu_to_le32(c->permissions); buf[1] = cpu_to_le32(nexpr); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; for (e = c->expr; e; e = e->next) { buf[0] = cpu_to_le32(e->expr_type); buf[1] = cpu_to_le32(e->attr); buf[2] = cpu_to_le32(e->op); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; switch (e->expr_type) { case CEXPR_NAMES: if (!allowxtarget && (e->attr & CEXPR_XTARGET)) return POLICYDB_ERROR; if (ebitmap_write(&e->names, fp)) { return POLICYDB_ERROR; } if ((p->policy_type != POLICY_KERN && type_set_write(e->type_names, fp)) || (p->policy_type == POLICY_KERN && (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) && type_set_write(e->type_names, fp))) { return POLICYDB_ERROR; } break; default: break; } } } return POLICYDB_SUCCESS; } static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { class_datum_t *cladatum; constraint_node_t *c; uint32_t buf[32], ncons; size_t items, items2, len, len2; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; cladatum = (class_datum_t *) datum; len = strlen(key); if (cladatum->comkey) len2 = strlen(cladatum->comkey); else len2 = 0; ncons = 0; for (c = cladatum->constraints; c; c = c->next) { ncons++; } items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(len2); buf[items++] = cpu_to_le32(cladatum->s.value); buf[items++] = cpu_to_le32(cladatum->permissions.nprim); if (cladatum->permissions.table) buf[items++] = cpu_to_le32(cladatum->permissions.table->nel); else buf[items++] = 0; buf[items++] = cpu_to_le32(ncons); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (cladatum->comkey) { items = put_entry(cladatum->comkey, 1, len2, fp); if (items != len2) return POLICYDB_ERROR; } if (hashtab_map(cladatum->permissions.table, perm_write, pd)) return POLICYDB_ERROR; if (write_cons_helper(p, cladatum->constraints, 0, fp)) return POLICYDB_ERROR; if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { /* write out the validatetrans rule */ ncons = 0; for (c = cladatum->validatetrans; c; c = c->next) { ncons++; } buf[0] = cpu_to_le32(ncons); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (write_cons_helper(p, cladatum->validatetrans, 1, fp)) return POLICYDB_ERROR; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { buf[0] = cpu_to_le32(cladatum->default_user); buf[1] = cpu_to_le32(cladatum->default_role); buf[2] = cpu_to_le32(cladatum->default_range); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { buf[0] = cpu_to_le32(cladatum->default_type); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { role_datum_t *role; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; role = (role_datum_t *) datum; /* * Role attributes are redundant for policy.X, skip them * when writing the roles symbol table. They are also skipped * when pp is downgraded. * * Their numbers would be deducted in policydb_write(). */ if ((role->flavor == ROLE_ATTRIB) && ((p->policy_type == POLICY_KERN) || (p->policy_type != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) return POLICYDB_SUCCESS; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(role->s.value); if (policydb_has_boundary_feature(p)) buf[items++] = cpu_to_le32(role->bounds); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (ebitmap_write(&role->dominates, fp)) return POLICYDB_ERROR; if (p->policy_type == POLICY_KERN) { if (role->s.value == OBJECT_R_VAL) { /* * CIL populates object_r's types map * rather than handling it as a special case. * However, this creates an inconsistency with * the kernel policy read from /sys/fs/selinux/policy * because the kernel ignores everything except for * object_r's value from the policy file. * Make them consistent by writing an empty * ebitmap instead. */ ebitmap_t empty; ebitmap_init(&empty); if (ebitmap_write(&empty, fp)) return POLICYDB_ERROR; } else { if (ebitmap_write(&role->types.types, fp)) return POLICYDB_ERROR; } } else { if (type_set_write(&role->types, fp)) return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { buf[0] = cpu_to_le32(role->flavor); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (ebitmap_write(&role->roles, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { type_datum_t *typdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; typdatum = (type_datum_t *) datum; /* * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY) * does not support to load entries of attribute, so we skip to write it. */ if (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_BOUNDARY && typdatum->flavor == TYPE_ATTRIB) return POLICYDB_SUCCESS; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(typdatum->s.value); if (policydb_has_boundary_feature(p)) { uint32_t properties = 0; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { buf[items++] = cpu_to_le32(typdatum->primary); } if (typdatum->primary) properties |= TYPEDATUM_PROPERTY_PRIMARY; if (typdatum->flavor == TYPE_ATTRIB) { properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; } else if (typdatum->flavor == TYPE_ALIAS && p->policy_type != POLICY_KERN) properties |= TYPEDATUM_PROPERTY_ALIAS; if (typdatum->flags & TYPE_FLAGS_PERMISSIVE && p->policy_type != POLICY_KERN) properties |= TYPEDATUM_PROPERTY_PERMISSIVE; buf[items++] = cpu_to_le32(properties); buf[items++] = cpu_to_le32(typdatum->bounds); } else { buf[items++] = cpu_to_le32(typdatum->primary); if (p->policy_type != POLICY_KERN) { buf[items++] = cpu_to_le32(typdatum->flavor); if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) buf[items++] = cpu_to_le32(typdatum->flags); else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE) WARN(fp->handle, "Warning! Module policy " "version %d cannot support permissive " "types, but one was defined", p->policyvers); } } items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; if (p->policy_type != POLICY_KERN) { if (ebitmap_write(&typdatum->types, fp)) return POLICYDB_ERROR; } items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { user_datum_t *usrdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; usrdatum = (user_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(usrdatum->s.value); if (policydb_has_boundary_feature(p)) buf[items++] = cpu_to_le32(usrdatum->bounds); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (p->policy_type == POLICY_KERN) { if (ebitmap_write(&usrdatum->roles.roles, fp)) return POLICYDB_ERROR; } else { if (role_set_write(&usrdatum->roles, fp)) return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_MOD) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_BASE)) { if (mls_write_range_helper(&usrdatum->exp_range, fp)) return POLICYDB_ERROR; if (mls_write_level(&usrdatum->exp_dfltlevel, fp)) return POLICYDB_ERROR; } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_MOD) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_BASE)) { if (mls_write_semantic_range_helper(&usrdatum->range, fp)) return -1; if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp)) return -1; } return POLICYDB_SUCCESS; } static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_write, class_write, role_write, type_write, user_write, cond_write_bool, sens_write, cat_write,}; static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, items, len; uint32_t buf[32]; ocontext_t *c; for (i = 0; i < info->ocon_num; i++) { nel = 0; for (c = p->ocontexts[i]; c; c = c->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = p->ocontexts[i]; c; c = c->next) { switch (i) { case OCON_XEN_ISID: buf[0] = cpu_to_le32(c->sid[0]); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_PIRQ: buf[0] = cpu_to_le32(c->u.pirq); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_IOPORT: buf[0] = c->u.ioport.low_ioport; buf[1] = c->u.ioport.high_ioport; for (j = 0; j < 2; j++) buf[j] = cpu_to_le32(buf[j]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_IOMEM: if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { uint64_t b64[2]; b64[0] = c->u.iomem.low_iomem; b64[1] = c->u.iomem.high_iomem; for (j = 0; j < 2; j++) b64[j] = cpu_to_le64(b64[j]); items = put_entry(b64, sizeof(uint64_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } else { if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) { ERR(fp->handle, "policy version %d" " cannot represent IOMEM addresses over 16TB", p->policyvers); return POLICYDB_ERROR; } buf[0] = c->u.iomem.low_iomem; buf[1] = c->u.iomem.high_iomem; for (j = 0; j < 2; j++) buf[j] = cpu_to_le32(buf[j]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_PCIDEVICE: buf[0] = cpu_to_le32(c->u.device); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_DEVICETREE: len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; } } } return POLICYDB_SUCCESS; } static int ocontext_write_selinux(struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, items, len; uint32_t buf[32]; ocontext_t *c; for (i = 0; i < info->ocon_num; i++) { nel = 0; for (c = p->ocontexts[i]; c; c = c->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = p->ocontexts[i]; c; c = c->next) { switch (i) { case OCON_ISID: buf[0] = cpu_to_le32(c->sid[0]); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_FS: case OCON_NETIF: len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; if (context_write(p, &c->context[1], fp)) return POLICYDB_ERROR; break; case OCON_IBPKEY: /* The subnet prefix is in network order */ memcpy(buf, &c->u.ibpkey.subnet_prefix, sizeof(c->u.ibpkey.subnet_prefix)); buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); items = put_entry(buf, sizeof(uint32_t), 4, fp); if (items != 4) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_IBENDPORT: len = strlen(c->u.ibendport.dev_name); buf[0] = cpu_to_le32(len); buf[1] = cpu_to_le32(c->u.ibendport.port); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; items = put_entry(c->u.ibendport.dev_name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_PORT: buf[0] = c->u.port.protocol; buf[1] = c->u.port.low_port; buf[2] = c->u.port.high_port; for (j = 0; j < 3; j++) { buf[j] = cpu_to_le32(buf[j]); } items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_NODE: buf[0] = c->u.node.addr; /* network order */ buf[1] = c->u.node.mask; /* network order */ items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_FSUSE: buf[0] = cpu_to_le32(c->v.behavior); len = strlen(c->u.name); buf[1] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_NODE6: for (j = 0; j < 4; j++) buf[j] = c->u.node6.addr[j]; /* network order */ for (j = 0; j < 4; j++) buf[j + 4] = c->u.node6.mask[j]; /* network order */ items = put_entry(buf, sizeof(uint32_t), 8, fp); if (items != 8) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; } } } return POLICYDB_SUCCESS; } static int ocontext_write(struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { int rc = POLICYDB_ERROR; switch (p->target_platform) { case SEPOL_TARGET_SELINUX: rc = ocontext_write_selinux(info, p, fp); break; case SEPOL_TARGET_XEN: rc = ocontext_write_xen(info, p, fp); break; } return rc; } static int genfs_write(policydb_t * p, struct policy_file *fp) { genfs_t *genfs; ocontext_t *c; size_t nel = 0, items, len; uint32_t buf[32]; for (genfs = p->genfs; genfs; genfs = genfs->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (genfs = p->genfs; genfs; genfs = genfs->next) { len = strlen(genfs->fstype); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(genfs->fstype, 1, len, fp); if (items != len) return POLICYDB_ERROR; nel = 0; for (c = genfs->head; c; c = c->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = genfs->head; c; c = c->next) { len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; buf[0] = cpu_to_le32(c->v.sclass); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } struct rangetrans_write_args { size_t nel; int new_rangetr; struct policy_file *fp; }; static int rangetrans_count(hashtab_key_t key, void *data __attribute__ ((unused)), void *ptr) { struct range_trans *rt = (struct range_trans *)key; struct rangetrans_write_args *args = ptr; /* all range_transitions are written for the new format, only process related range_transitions are written for the old format, so count accordingly */ if (args->new_rangetr || rt->target_class == SECCLASS_PROCESS) args->nel++; return 0; } static int range_write_helper(hashtab_key_t key, void *data, void *ptr) { uint32_t buf[2]; struct range_trans *rt = (struct range_trans *)key; struct mls_range *r = data; struct rangetrans_write_args *args = ptr; struct policy_file *fp = args->fp; int new_rangetr = args->new_rangetr; size_t items; static int warning_issued = 0; int rc; if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) { if (!warning_issued) WARN(fp->handle, "Discarding range_transition " "rules for security classes other than " "\"process\""); warning_issued = 1; return 0; } buf[0] = cpu_to_le32(rt->source_type); buf[1] = cpu_to_le32(rt->target_type); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (new_rangetr) { buf[0] = cpu_to_le32(rt->target_class); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } rc = mls_write_range_helper(r, fp); if (rc) return rc; return 0; } static int range_write(policydb_t * p, struct policy_file *fp) { size_t items; uint32_t buf[2]; int new_rangetr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_RANGETRANS); struct rangetrans_write_args args; int rc; args.nel = 0; args.new_rangetr = new_rangetr; args.fp = fp; rc = hashtab_map(p->range_tr, rangetrans_count, &args); if (rc) return rc; buf[0] = cpu_to_le32(args.nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return hashtab_map(p->range_tr, range_write_helper, &args); } /************** module writing functions below **************/ static int avrule_write(policydb_t *p, avrule_t * avrule, struct policy_file *fp) { size_t items, items2; uint32_t buf[32], len; class_perm_node_t *cur; items = 0; buf[items++] = cpu_to_le32(avrule->specified); buf[items++] = cpu_to_le32(avrule->flags); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if (type_set_write(&avrule->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&avrule->ttypes, fp)) return POLICYDB_ERROR; cur = avrule->perms; len = 0; while (cur) { len++; cur = cur->next; } items = 0; buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; cur = avrule->perms; while (cur) { items = 0; buf[items++] = cpu_to_le32(cur->tclass); buf[items++] = cpu_to_le32(cur->data); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; cur = cur->next; } if (avrule->specified & AVRULE_XPERMS) { size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; uint8_t buf8; unsigned int i; if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ERR(fp->handle, "module policy version %u does not support ioctl" " extended permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } if (p->target_platform != SEPOL_TARGET_SELINUX) { ERR(fp->handle, "Target platform %s does not support ioctl" " extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; } buf8 = avrule->xperms->specified; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; buf8 = avrule->xperms->driver; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; for (i = 0; i < nel; i++) buf32[i] = cpu_to_le32(avrule->xperms->perms[i]); items = put_entry(buf32, sizeof(uint32_t), nel, fp); if (items != nel) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int avrule_write_list(policydb_t *p, avrule_t * avrules, struct policy_file *fp) { uint32_t buf[32], len; avrule_t *avrule; avrule = avrules; len = 0; while (avrule) { len++; avrule = avrule->next; } buf[0] = cpu_to_le32(len); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) return POLICYDB_ERROR; avrule = avrules; while (avrule) { if (avrule_write(p, avrule, fp)) return POLICYDB_ERROR; avrule = avrule->next; } return POLICYDB_SUCCESS; } static int only_process(ebitmap_t *in) { unsigned int i; ebitmap_node_t *node; ebitmap_for_each_bit(in, node, i) { if (ebitmap_node_get_bit(node, i) && i != SECCLASS_PROCESS - 1) return 0; } return 1; } static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; role_trans_rule_t *tr; int warned = 0; int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS; for (tr = t; tr; tr = tr->next) if (new_role || only_process(&tr->classes)) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (tr = t; tr; tr = tr->next) { if (!new_role && !only_process(&tr->classes)) { if (!warned) WARN(fp->handle, "Discarding role_transition " "rules for security classes other than " "\"process\""); warned = 1; continue; } if (role_set_write(&tr->roles, fp)) return POLICYDB_ERROR; if (type_set_write(&tr->types, fp)) return POLICYDB_ERROR; if (new_role) if (ebitmap_write(&tr->classes, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(tr->new_role); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; role_allow_rule_t *ra; for (ra = r; ra; ra = ra->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ra = r; ra; ra = ra->next) { if (role_set_write(&ra->roles, fp)) return POLICYDB_ERROR; if (role_set_write(&ra->new_roles, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[2], len; filename_trans_rule_t *ftr; for (ftr = t; ftr; ftr = ftr->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ftr = t; ftr; ftr = ftr->next) { len = strlen(ftr->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(ftr->name, sizeof(char), len, fp); if (items != len) return POLICYDB_ERROR; if (type_set_write(&ftr->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&ftr->ttypes, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(ftr->tclass); buf[1] = cpu_to_le32(ftr->otype); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int range_trans_rule_write(range_trans_rule_t * t, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; range_trans_rule_t *rt; for (rt = t; rt; rt = rt->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (rt = t; rt; rt = rt->next) { if (type_set_write(&rt->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&rt->ttypes, fp)) return POLICYDB_ERROR; if (ebitmap_write(&rt->tclasses, fp)) return POLICYDB_ERROR; if (mls_write_semantic_range_helper(&rt->trange, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int scope_index_write(scope_index_t * scope_index, unsigned int num_scope_syms, struct policy_file *fp) { unsigned int i; uint32_t buf[1]; for (i = 0; i < num_scope_syms; i++) { if (ebitmap_write(scope_index->scope + i, fp) == -1) { return POLICYDB_ERROR; } } buf[0] = cpu_to_le32(scope_index->class_perms_len); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } for (i = 0; i < scope_index->class_perms_len; i++) { if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) { return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, policydb_t * p, struct policy_file *fp) { struct policy_data pd; uint32_t buf[2]; int i; buf[0] = cpu_to_le32(decl->decl_id); buf[1] = cpu_to_le32(decl->enabled); if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { return POLICYDB_ERROR; } if (cond_write_list(p, decl->cond_list, fp) == -1 || avrule_write_list(p, decl->avrules, fp) == -1 || role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || role_allow_rule_write(decl->role_allow_rules, fp) == -1) { return POLICYDB_ERROR; } if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && filename_trans_rule_write(decl->filename_trans_rules, fp)) return POLICYDB_ERROR; if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && range_trans_rule_write(decl->range_tr_rules, fp) == -1) { return POLICYDB_ERROR; } if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 || scope_index_write(&decl->declared, num_scope_syms, fp) == -1) { return POLICYDB_ERROR; } pd.fp = fp; pd.p = p; for (i = 0; i < num_scope_syms; i++) { buf[0] = cpu_to_le32(decl->symtab[i].nprim); buf[1] = cpu_to_le32(decl->symtab[i].table->nel); if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { return POLICYDB_ERROR; } if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) { return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int avrule_block_write(avrule_block_t * block, int num_scope_syms, policydb_t * p, struct policy_file *fp) { /* first write a count of the total number of blocks */ uint32_t buf[1], num_blocks = 0; avrule_block_t *cur; for (cur = block; cur != NULL; cur = cur->next) { num_blocks++; } buf[0] = cpu_to_le32(num_blocks); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } /* now write each block */ for (cur = block; cur != NULL; cur = cur->next) { uint32_t num_decls = 0; avrule_decl_t *decl; /* write a count of number of branches */ for (decl = cur->branch_list; decl != NULL; decl = decl->next) { num_decls++; } buf[0] = cpu_to_le32(num_decls); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (avrule_decl_write(decl, num_scope_syms, p, fp) == -1) { return POLICYDB_ERROR; } } } return POLICYDB_SUCCESS; } static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { scope_datum_t *scope = (scope_datum_t *) datum; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; uint32_t static_buf[32], *dyn_buf = NULL, *buf; size_t key_len = strlen(key); unsigned int items = 2 + scope->decl_ids_len, i; int rc; buf = static_buf; if (items >= (sizeof(static_buf) / 4)) { /* too many things required, so dynamically create a * buffer. this would have been easier with C99's * dynamic arrays... */ rc = POLICYDB_ERROR; dyn_buf = malloc(items * sizeof(*dyn_buf)); if (!dyn_buf) goto err; buf = dyn_buf; } buf[0] = cpu_to_le32(key_len); rc = POLICYDB_ERROR; if (put_entry(buf, sizeof(*buf), 1, fp) != 1 || put_entry(key, 1, key_len, fp) != key_len) goto err; buf[0] = cpu_to_le32(scope->scope); buf[1] = cpu_to_le32(scope->decl_ids_len); for (i = 0; i < scope->decl_ids_len; i++) buf[2 + i] = cpu_to_le32(scope->decl_ids[i]); rc = POLICYDB_ERROR; if (put_entry(buf, sizeof(*buf), items, fp) != items) goto err; rc = POLICYDB_SUCCESS; err: free(dyn_buf); return rc; } static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *args) { type_datum_t *typdatum = datum; uint32_t *p_nel = args; if (typdatum->flavor == TYPE_ATTRIB) { /* uncount attribute from total number of types */ (*p_nel)--; } return 0; } static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *args) { role_datum_t *role = datum; uint32_t *p_nel = args; if (role->flavor == ROLE_ATTRIB) { /* uncount attribute from total number of roles */ (*p_nel)--; } return 0; } /* * Write the configuration data in a policy database * structure to a policy database binary representation * file. */ int policydb_write(policydb_t * p, struct policy_file *fp) { unsigned int i, num_syms; uint32_t buf[32], config; size_t items, items2, len; struct policydb_compat_info *info; struct policy_data pd; const char *policydb_str; if (p->unsupported_format) return POLICYDB_UNSUPPORTED; pd.fp = fp; pd.p = p; config = 0; if (p->mls) { if ((p->policyvers < POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_BASE) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_MOD)) { ERR(fp->handle, "policy version %d cannot support MLS", p->policyvers); return POLICYDB_ERROR; } config |= POLICYDB_CONFIG_MLS; } config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown); /* Write the magic number and string identifiers. */ items = 0; if (p->policy_type == POLICY_KERN) { buf[items++] = cpu_to_le32(POLICYDB_MAGIC); len = strlen(policydb_target_strings[p->target_platform]); policydb_str = policydb_target_strings[p->target_platform]; } else { buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC); len = strlen(POLICYDB_MOD_STRING); policydb_str = POLICYDB_MOD_STRING; } buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(policydb_str, 1, len, fp); if (items != len) return POLICYDB_ERROR; /* Write the version, config, and table sizes. */ items = 0; info = policydb_lookup_compat(p->policyvers, p->policy_type, p->target_platform); if (!info) { ERR(fp->handle, "compatibility lookup failed for policy " "version %d", p->policyvers); return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN) { buf[items++] = cpu_to_le32(p->policy_type); } buf[items++] = cpu_to_le32(p->policyvers); buf[items++] = cpu_to_le32(config); buf[items++] = cpu_to_le32(info->sym_num); buf[items++] = cpu_to_le32(info->ocon_num); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; if (p->policy_type == POLICY_MOD) { /* Write module name and version */ len = strlen(p->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(p->name, 1, len, fp); if (items != len) return POLICYDB_ERROR; len = strlen(p->version); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(p->version, 1, len, fp); if (items != len) return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_BASE) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_MOD)) { if (ebitmap_write(&p->policycaps, fp) == -1) return POLICYDB_ERROR; } if (p->policyvers < POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { ebitmap_node_t *tnode; ebitmap_for_each_bit(&p->permissive_map, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { WARN(fp->handle, "Warning! Policy version %d cannot " "support permissive types, but some were defined", p->policyvers); break; } } } if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { if (ebitmap_write(&p->permissive_map, fp) == -1) return POLICYDB_ERROR; } num_syms = info->sym_num; for (i = 0; i < num_syms; i++) { buf[0] = cpu_to_le32(p->symtab[i].nprim); buf[1] = p->symtab[i].table->nel; /* * A special case when writing type/attribute symbol table. * The kernel policy version less than 24 does not support * to load entries of attribute, so we have to re-calculate * the actual number of types except for attributes. */ if (i == SYM_TYPES && p->policyvers < POLICYDB_VERSION_BOUNDARY && p->policy_type == POLICY_KERN) { hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]); } /* * Another special case when writing role/attribute symbol * table, role attributes are redundant for policy.X, or * when the pp's version is not big enough. So deduct * their numbers from p_roles.table->nel. */ if ((i == SYM_ROLES) && ((p->policy_type == POLICY_KERN) || (p->policy_type != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]); buf[1] = cpu_to_le32(buf[1]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (hashtab_map(p->symtab[i].table, write_f[i], &pd)) return POLICYDB_ERROR; } if (p->policy_type == POLICY_KERN) { if (avtab_write(p, &p->te_avtab, fp)) return POLICYDB_ERROR; if (p->policyvers < POLICYDB_VERSION_BOOL) { if (p->p_bools.nprim) WARN(fp->handle, "Discarding " "booleans and conditional rules"); } else { if (cond_write_list(p, p->cond_list, fp)) return POLICYDB_ERROR; } if (role_trans_write(p, fp)) return POLICYDB_ERROR; if (role_allow_write(p->role_allow, fp)) return POLICYDB_ERROR; if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) { if (filename_trans_write(p, fp)) return POLICYDB_ERROR; } else { if (p->filename_trans) WARN(fp->handle, "Discarding filename type transition rules"); } } else { if (avrule_block_write(p->global, num_syms, p, fp) == -1) { return POLICYDB_ERROR; } for (i = 0; i < num_syms; i++) { buf[0] = cpu_to_le32(p->scope[i].table->nel); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } if (hashtab_map(p->scope[i].table, scope_write, &pd)) return POLICYDB_ERROR; } } if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) { return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS && p->policy_type == POLICY_BASE)) { if (range_write(p, fp)) { return POLICYDB_ERROR; } } if (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_AVTAB) { for (i = 0; i < p->p_types.nprim; i++) { if (ebitmap_write(&p->type_attr_map[i], fp) == -1) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } libsepol/tests/0040755 0000000 0000000 00000000000 13756670065 012602 5ustar000000000 0000000 libsepol/tests/.gitignore0100644 0000000 0000000 00000000017 13756670065 014565 0ustar000000000 0000000 libsepol-tests libsepol/tests/Makefile0100644 0000000 0000000 00000003417 13756670065 014244 0ustar000000000 0000000 M4 ?= m4 MKDIR ?= mkdir EXE ?= libsepol-tests CFLAGS += -g3 -gdwarf-2 -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter -Werror # Statically link libsepol on the assumption that we are going to # be testing internal functions. LIBSEPOL := ../src/libsepol.a # In order to load source policies we need to link in the checkpolicy/checkmodule parser and util code. # This is less than ideal, but it makes the tests easier to maintain by allowing source policies # to be loaded directly. CHECKPOLICY := ../../checkpolicy/ override CPPFLAGS += -I../include/ -I$(CHECKPOLICY) # test program object files objs := $(patsubst %.c,%.o,$(sort $(wildcard *.c))) parserobjs := $(CHECKPOLICY)queue.o $(CHECKPOLICY)y.tab.o \ $(CHECKPOLICY)parse_util.o $(CHECKPOLICY)lex.yy.o \ $(CHECKPOLICY)policy_define.o $(CHECKPOLICY)module_compiler.o # test policy pieces m4support := $(wildcard policies/support/*.spt) testsuites := $(wildcard policies/test-*) policysrc := $(foreach path,$(testsuites),$(wildcard $(path)/*.conf)) stdpol := $(addsuffix .std,$(policysrc)) mlspol := $(addsuffix .mls,$(policysrc)) policies := $(stdpol) $(mlspol) all: $(EXE) $(policies) policies: $(policies) $(EXE): $(objs) $(parserobjs) $(LIBSEPOL) $(CC) $(LDFLAGS) $(objs) $(parserobjs) -lcunit -lcurses $(LIBSEPOL) -o $@ %.conf.std: $(m4support) %.conf $(M4) $(M4PARAMS) $^ > $@ %.conf.mls: $(m4support) %.conf $(M4) $(M4PARAMS) -D enable_mls $^ > $@ clean: rm -f $(objs) $(EXE) rm -f $(policies) rm -f policies/test-downgrade/policy.hi policies/test-downgrade/policy.lo test: $(EXE) $(policies) $(MKDIR) -p policies/test-downgrade ../../checkpolicy/checkpolicy -M policies/test-cond/refpolicy-base.conf -o policies/test-downgrade/policy.hi ./$(EXE) .PHONY: all policies clean test libsepol/tests/debug.c0100644 0000000 0000000 00000003443 13756670065 014035 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This includes functions used to debug tests (display bitmaps, conditional expressions, etc */ #include "debug.h" #include void print_ebitmap(ebitmap_t * bitmap, FILE * fp) { uint32_t i; for (i = 0; i < bitmap->highbit; i++) { fprintf(fp, "%d", ebitmap_get_bit(bitmap, i)); } fprintf(fp, "\n"); } /* stolen from dispol.c */ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", p->p_bool_val_to_name[cur->bool - 1]); break; case COND_NOT: fprintf(fp, "! "); break; case COND_OR: fprintf(fp, "|| "); break; case COND_AND: fprintf(fp, "&& "); break; case COND_XOR: fprintf(fp, "^ "); break; case COND_EQ: fprintf(fp, "== "); break; case COND_NEQ: fprintf(fp, "!= "); break; default: fprintf(fp, "error! (%d)", cur->expr_type); break; } } } libsepol/tests/debug.h0100644 0000000 0000000 00000002211 13756670065 014032 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This includes functions used to debug tests (display bitmaps, conditional expressions, etc */ #include #include extern void print_ebitmap(ebitmap_t * bitmap, FILE * fp); extern void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp); libsepol/tests/helpers.c0100644 0000000 0000000 00000004223 13756670065 014406 0ustar000000000 0000000 /* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This has helper functions that are common between tests */ #include "helpers.h" #include "parse_util.h" #include #include #include #include #include int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_name, const char *policy_name) { char filename[PATH_MAX]; if (mls) { if (snprintf(filename, PATH_MAX, "policies/%s/%s.mls", test_name, policy_name) < 0) { return -1; } } else { if (snprintf(filename, PATH_MAX, "policies/%s/%s.std", test_name, policy_name) < 0) { return -1; } } if (policydb_init(p)) { fprintf(stderr, "Out of memory"); return -1; } p->policy_type = policy_type; p->mls = mls; if (read_source_policy(p, filename, test_name)) { fprintf(stderr, "failed to read policy %s\n", filename); policydb_destroy(p); return -1; } return 0; } avrule_decl_t *test_find_decl_by_sym(policydb_t * p, int symtab, const char *sym) { scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symtab].table, sym); if (scope == NULL) { return NULL; } if (scope->scope != SCOPE_DECL) { return NULL; } if (scope->decl_ids_len != 1) { return NULL; } return p->decl_val_to_struct[scope->decl_ids[0] - 1]; } libsepol/tests/helpers.h0100644 0000000 0000000 00000004366 13756670065 014423 0ustar000000000 0000000 /* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __COMMON_H__ #define __COMMON_H__ #include #include /* helper functions */ /* Load a source policy into p. policydb_init will called within this function. * * Example: test_load_policy(p, POLICY_BASE, 1, "foo", "base.conf") will load the * policy "policies/foo/mls/base.conf" into p. * * Arguments: * p policydb_t into which the policy will be read. This should be * malloc'd but not passed to policydb_init. * policy_type Type of policy expected - POLICY_BASE or POLICY_MOD. * mls Boolean value indicating whether an mls policy is expected. * test_name Name of the test which will be the name of the directory in * which the policies are stored. * policy_name Name of the policy in the directory. * * Returns: * 0 success * -1 error - the policydb will be destroyed but not freed. */ extern int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_name, const char *policy_name); /* Find an avrule_decl_t by a unique symbol. If the symbol is declared in more * than one decl an error is returned. * * Returns: * decl success * NULL error (including more than one declaration) */ extern avrule_decl_t *test_find_decl_by_sym(policydb_t * p, int symtab, const char *sym); #endif libsepol/tests/libsepol-tests.c0100644 0000000 0000000 00000005445 13756670065 015724 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-cond.h" #include "test-linker.h" #include "test-expander.h" #include "test-deps.h" #include "test-downgrade.h" #include #include #include #include #include #include #include int mls; #define DECLARE_SUITE(name) \ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \ if (NULL == suite) { \ CU_cleanup_registry(); \ return CU_get_error(); } \ if (name##_add_tests(suite)) { \ CU_cleanup_registry(); \ return CU_get_error(); } static void usage(char *progname) { printf("usage: %s [options]\n", progname); printf("options:\n"); printf("\t-v, --verbose\t\t\tverbose output\n"); printf("\t-i, --interactive\t\tinteractive console\n"); } static bool do_tests(int interactive, int verbose) { CU_pSuite suite = NULL; unsigned int num_failures; if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); DECLARE_SUITE(cond); DECLARE_SUITE(linker); DECLARE_SUITE(expander); DECLARE_SUITE(deps); DECLARE_SUITE(downgrade); if (verbose) CU_basic_set_mode(CU_BRM_VERBOSE); else CU_basic_set_mode(CU_BRM_NORMAL); if (interactive) CU_console_run_tests(); else CU_basic_run_tests(); num_failures = CU_get_number_of_tests_failed(); CU_cleanup_registry(); return CU_get_error() == CUE_SUCCESS && num_failures == 0; } int main(int argc, char **argv) { int i, verbose = 1, interactive = 0; struct option opts[] = { {"verbose", 0, NULL, 'v'}, {"interactive", 0, NULL, 'i'}, {NULL, 0, NULL, 0} }; while ((i = getopt_long(argc, argv, "vi", opts, NULL)) != -1) { switch (i) { case 'v': verbose = 1; break; case 'i': interactive = 1; break; case 'h': default:{ usage(argv[0]); exit(1); } } } /* first do the non-mls tests */ mls = 0; if (!do_tests(interactive, verbose)) return -1; /* then with mls */ mls = 1; if (!do_tests(interactive, verbose)) return -1; return 0; } libsepol/tests/policies/0040755 0000000 0000000 00000000000 13756670065 014411 5ustar000000000 0000000 libsepol/tests/policies/.gitignore0100644 0000000 0000000 00000000052 13756670065 016373 0ustar000000000 0000000 test-downgrade/ test-*/*.mls test-*/*.std libsepol/tests/policies/support/0040755 0000000 0000000 00000000000 13756670065 016125 5ustar000000000 0000000 libsepol/tests/policies/support/misc_macros.spt0100644 0000000 0000000 00000001175 13756670065 021155 0ustar000000000 0000000 ######################################## # # Helper macros # ######################################## # # gen_user(username, prefix, role_set, mls_defaultlevel, mls_range, [mcs_categories]) # define(`gen_user',`dnl ifdef(`users_extra',`dnl ifelse(`$2',,,`user $1 prefix $2;') ',`dnl user $1 roles { $3 }`'ifdef(`enable_mls', ` level $4 range $5')`'ifdef(`enable_mcs',` level s0 range s0`'ifelse(`$6',,,` - s0:$6')'); ')dnl ') ######################################## # # gen_context(context,mls_sensitivity,[mcs_categories]) # define(`gen_context',`$1`'ifdef(`enable_mls',`:$2')`'ifdef(`enable_mcs',`:s0`'ifelse(`$3',,,`:$3')')') dnl libsepol/tests/policies/test-cond/0040755 0000000 0000000 00000000000 13756670065 016311 5ustar000000000 0000000 libsepol/tests/policies/test-cond/refpolicy-base.conf0100644 0000000 0000000 00000206116 13756670065 022067 0ustar000000000 0000000 class security class process class system class capability class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket class sem class msg class msgq class shm class ipc class passwd # userspace class drawable # userspace class window # userspace class gc # userspace class font # userspace class colormap # userspace class property # userspace class cursor # userspace class xclient # userspace class xinput # userspace class xserver # userspace class xextension # userspace class pax class netlink_route_socket class netlink_firewall_socket class netlink_tcpdiag_socket class netlink_nflog_socket class netlink_xfrm_socket class netlink_selinux_socket class netlink_audit_socket class netlink_ip6fw_socket class netlink_dnrt_socket class dbus # userspace class nscd # userspace class association class netlink_kobject_uevent_socket sid kernel sid security sid unlabeled sid fs sid file sid file_labels sid init sid any_socket sid port sid netif sid netmsg sid node sid igmp_packet sid icmp_socket sid tcp_socket sid sysctl_modprobe sid sysctl sid sysctl_fs sid sysctl_kernel sid sysctl_net sid sysctl_net_unix sid sysctl_vm sid sysctl_dev sid kmod sid policy sid scmp_packet sid devnull common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } common socket { ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } common ipc { create destroy getattr setattr read write associate unix_read unix_write } class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint execmod } class lnk_file inherits file class chr_file inherits file { execute_no_trans entrypoint execmod } class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom node_bind name_connect } class udp_socket inherits socket { node_bind } class rawip_socket inherits socket { node_bind } class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap } class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } class security { compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce # was avc_toggle in system class setbool setsecparam setcheckreqprot } class system { ipc_info syslog_read syslog_mod syslog_console } class capability { chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control } class passwd { passwd # change another user passwd chfn # change another user finger info chsh # change another user shell rootok # pam_rootok check (skip auth) crontab # crontab on another user } class drawable { create destroy draw copy getattr } class gc { create free getattr setattr } class window { addchild create destroy map unmap chstack chproplist chprop listprop getattr setattr setfocus move chselection chparent ctrllife enumerate transparent mousemotion clientcomevent inputevent drawevent windowchangeevent windowchangerequest serverchangeevent extensionevent } class font { load free getattr use } class colormap { create free install uninstall list read store getattr setattr } class property { create free read write } class cursor { create createglyph free assign setattr } class xclient { kill } class xinput { lookup getattr setattr setfocus warppointer activegrab passivegrab ungrab bell mousemotion relabelinput } class xserver { screensaver gethostlist sethostlist getfontpath setfontpath getattr grab ungrab } class xextension { query use } class pax { pageexec # Paging based non-executable pages emutramp # Emulate trampolines mprotect # Restrict mprotect() randmmap # Randomize mmap() base randexec # Randomize ET_EXEC base segmexec # Segmentation based non-executable pages } class netlink_route_socket inherits socket { nlmsg_read nlmsg_write } class netlink_firewall_socket inherits socket { nlmsg_read nlmsg_write } class netlink_tcpdiag_socket inherits socket { nlmsg_read nlmsg_write } class netlink_nflog_socket inherits socket class netlink_xfrm_socket inherits socket { nlmsg_read nlmsg_write } class netlink_selinux_socket inherits socket class netlink_audit_socket inherits socket { nlmsg_read nlmsg_write nlmsg_relay nlmsg_readpriv } class netlink_ip6fw_socket inherits socket { nlmsg_read nlmsg_write } class netlink_dnrt_socket inherits socket class dbus { acquire_svc send_msg } class nscd { getpwd getgrp gethost getstat admin shmempwd shmemgrp shmemhost } class association { sendto recvfrom setcontext } class netlink_kobject_uevent_socket inherits socket sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; category c24; category c25; category c26; category c27; category c28; category c29; category c30; category c31; category c32; category c33; category c34; category c35; category c36; category c37; category c38; category c39; category c40; category c41; category c42; category c43; category c44; category c45; category c46; category c47; category c48; category c49; category c50; category c51; category c52; category c53; category c54; category c55; category c56; category c57; category c58; category c59; category c60; category c61; category c62; category c63; category c64; category c65; category c66; category c67; category c68; category c69; category c70; category c71; category c72; category c73; category c74; category c75; category c76; category c77; category c78; category c79; category c80; category c81; category c82; category c83; category c84; category c85; category c86; category c87; category c88; category c89; category c90; category c91; category c92; category c93; category c94; category c95; category c96; category c97; category c98; category c99; category c100; category c101; category c102; category c103; category c104; category c105; category c106; category c107; category c108; category c109; category c110; category c111; category c112; category c113; category c114; category c115; category c116; category c117; category c118; category c119; category c120; category c121; category c122; category c123; category c124; category c125; category c126; category c127; category c128; category c129; category c130; category c131; category c132; category c133; category c134; category c135; category c136; category c137; category c138; category c139; category c140; category c141; category c142; category c143; category c144; category c145; category c146; category c147; category c148; category c149; category c150; category c151; category c152; category c153; category c154; category c155; category c156; category c157; category c158; category c159; category c160; category c161; category c162; category c163; category c164; category c165; category c166; category c167; category c168; category c169; category c170; category c171; category c172; category c173; category c174; category c175; category c176; category c177; category c178; category c179; category c180; category c181; category c182; category c183; category c184; category c185; category c186; category c187; category c188; category c189; category c190; category c191; category c192; category c193; category c194; category c195; category c196; category c197; category c198; category c199; category c200; category c201; category c202; category c203; category c204; category c205; category c206; category c207; category c208; category c209; category c210; category c211; category c212; category c213; category c214; category c215; category c216; category c217; category c218; category c219; category c220; category c221; category c222; category c223; category c224; category c225; category c226; category c227; category c228; category c229; category c230; category c231; category c232; category c233; category c234; category c235; category c236; category c237; category c238; category c239; category c240; category c241; category c242; category c243; category c244; category c245; category c246; category c247; category c248; category c249; category c250; category c251; category c252; category c253; category c254; category c255; level s0:c0.c255; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } (h1 dom h2); mlsconstrain file { create relabelto } ((h1 dom h2) and (l2 eq h2)); mlsconstrain file { read } ((h1 dom h2) or ( t2 == domain ) or ( t1 == mlsfileread )); mlsconstrain { dir lnk_file chr_file blk_file sock_file fifo_file } { relabelfrom } ( h1 dom h2 ); mlsconstrain { dir lnk_file chr_file blk_file sock_file fifo_file } { create relabelto } (( h1 dom h2 ) and ( l2 eq h2 )); mlsconstrain process { ptrace } ( h1 dom h2 ); mlsconstrain process { sigkill sigstop } ( h1 dom h2 ) or ( t1 == mcskillall ); mlsconstrain xextension query ( t1 == mlsfileread ); attribute netif_type; attribute node_type; attribute port_type; attribute reserved_port_type; attribute device_node; attribute memory_raw_read; attribute memory_raw_write; attribute domain; attribute unconfined_domain_type; attribute set_curr_context; attribute entry_type; attribute privfd; attribute can_change_process_identity; attribute can_change_process_role; attribute can_change_object_identity; attribute can_system_change; attribute process_user_target; attribute cron_source_domain; attribute cron_job_domain; attribute process_uncond_exempt; # add userhelperdomain to this one attribute file_type; attribute lockfile; attribute mountpoint; attribute pidfile; attribute polydir; attribute usercanread; attribute polyparent; attribute polymember; attribute security_file_type; attribute tmpfile; attribute tmpfsfile; attribute filesystem_type; attribute noxattrfs; attribute can_load_kernmodule; attribute can_receive_kernel_messages; attribute kern_unconfined; attribute proc_type; attribute sysctl_type; attribute mcskillall; attribute mlsfileread; attribute mlsfilereadtoclr; attribute mlsfilewrite; attribute mlsfilewritetoclr; attribute mlsfileupgrade; attribute mlsfiledowngrade; attribute mlsnetread; attribute mlsnetreadtoclr; attribute mlsnetwrite; attribute mlsnetwritetoclr; attribute mlsnetupgrade; attribute mlsnetdowngrade; attribute mlsnetrecvall; attribute mlsipcread; attribute mlsipcreadtoclr; attribute mlsipcwrite; attribute mlsipcwritetoclr; attribute mlsprocread; attribute mlsprocreadtoclr; attribute mlsprocwrite; attribute mlsprocwritetoclr; attribute mlsprocsetsl; attribute mlsxwinread; attribute mlsxwinreadtoclr; attribute mlsxwinwrite; attribute mlsxwinwritetoclr; attribute mlsxwinreadproperty; attribute mlsxwinwriteproperty; attribute mlsxwinreadcolormap; attribute mlsxwinwritecolormap; attribute mlsxwinwritexinput; attribute mlstrustedobject; attribute privrangetrans; attribute mlsrangetrans; attribute can_load_policy; attribute can_setenforce; attribute can_setsecparam; attribute ttynode; attribute ptynode; attribute server_ptynode; attribute serial_device; type bin_t; type sbin_t; type ls_exec_t; type shell_exec_t; type chroot_exec_t; type ppp_device_t; type tun_tap_device_t; type port_t, port_type; type reserved_port_t, port_type, reserved_port_type; type afs_bos_port_t, port_type; type afs_fs_port_t, port_type; type afs_ka_port_t, port_type; type afs_pt_port_t, port_type; type afs_vl_port_t, port_type; type amanda_port_t, port_type; type amavisd_recv_port_t, port_type; type amavisd_send_port_t, port_type; type asterisk_port_t, port_type; type auth_port_t, port_type; type bgp_port_t, port_type; type biff_port_t, port_type, reserved_port_type; type clamd_port_t, port_type; type clockspeed_port_t, port_type; type comsat_port_t, port_type; type cvs_port_t, port_type; type dcc_port_t, port_type; type dbskkd_port_t, port_type; type dhcpc_port_t, port_type; type dhcpd_port_t, port_type; type dict_port_t, port_type; type distccd_port_t, port_type; type dns_port_t, port_type; type fingerd_port_t, port_type; type ftp_data_port_t, port_type; type ftp_port_t, port_type; type gatekeeper_port_t, port_type; type giftd_port_t, port_type; type gopher_port_t, port_type; type http_cache_port_t, port_type; type http_port_t, port_type; type howl_port_t, port_type; type hplip_port_t, port_type; type i18n_input_port_t, port_type; type imaze_port_t, port_type; type inetd_child_port_t, port_type; type innd_port_t, port_type; type ipp_port_t, port_type; type ircd_port_t, port_type; type isakmp_port_t, port_type; type jabber_client_port_t, port_type; type jabber_interserver_port_t, port_type; type kerberos_admin_port_t, port_type; type kerberos_master_port_t, port_type; type kerberos_port_t, port_type; type ktalkd_port_t, port_type; type ldap_port_t, port_type; type lrrd_port_t, port_type; type mail_port_t, port_type; type monopd_port_t, port_type; type mysqld_port_t, port_type; type nessus_port_t, port_type; type nmbd_port_t, port_type; type ntp_port_t, port_type; type openvpn_port_t, port_type; type pegasus_http_port_t, port_type; type pegasus_https_port_t, port_type; type pop_port_t, port_type; type portmap_port_t, port_type; type postgresql_port_t, port_type; type postgrey_port_t, port_type; type printer_port_t, port_type; type ptal_port_t, port_type; type pxe_port_t, port_type; type pyzor_port_t, port_type; type radacct_port_t, port_type; type radius_port_t, port_type; type razor_port_t, port_type; type rlogind_port_t, port_type; type rndc_port_t, port_type; type router_port_t, port_type; type rsh_port_t, port_type; type rsync_port_t, port_type; type smbd_port_t, port_type; type smtp_port_t, port_type; type snmp_port_t, port_type; type spamd_port_t, port_type; type ssh_port_t, port_type; type soundd_port_t, port_type; type socks_port_t, port_type; type stunnel_port_t, port_type; type swat_port_t, port_type; type syslogd_port_t, port_type; type telnetd_port_t, port_type; type tftp_port_t, port_type; type transproxy_port_t, port_type; type utcpserver_port_t, port_type; type uucpd_port_t, port_type; type vnc_port_t, port_type; type xserver_port_t, port_type; type xen_port_t, port_type; type zebra_port_t, port_type; type zope_port_t, port_type; type node_t, node_type; type compat_ipv4_node_t alias node_compat_ipv4_t, node_type; type inaddr_any_node_t alias node_inaddr_any_t, node_type; type node_internal_t, node_type; type link_local_node_t alias node_link_local_t, node_type; type lo_node_t alias node_lo_t, node_type; type mapped_ipv4_node_t alias node_mapped_ipv4_t, node_type; type multicast_node_t alias node_multicast_t, node_type; type site_local_node_t alias node_site_local_t, node_type; type unspec_node_t alias node_unspec_t, node_type; type netif_t, netif_type; type device_t; type agp_device_t; type apm_bios_t; type cardmgr_dev_t; type clock_device_t; type cpu_device_t; type crypt_device_t; type dri_device_t; type event_device_t; type framebuf_device_t; type lvm_control_t; type memory_device_t; type misc_device_t; type mouse_device_t; type mtrr_device_t; type null_device_t; type power_device_t; type printer_device_t; type random_device_t; type scanner_device_t; type sound_device_t; type sysfs_t; type urandom_device_t; type usbfs_t alias usbdevfs_t; type usb_device_t; type v4l_device_t; type xserver_misc_device_t; type zero_device_t; type xconsole_device_t; type devfs_control_t; type boot_t; type default_t, file_type, mountpoint; type etc_t, file_type; type etc_runtime_t, file_type; type file_t, file_type, mountpoint; type home_root_t, file_type, mountpoint; type lost_found_t, file_type; type mnt_t, file_type, mountpoint; type modules_object_t; type no_access_t, file_type; type poly_t, file_type; type readable_t, file_type; type root_t, file_type, mountpoint; type src_t, file_type, mountpoint; type system_map_t; type tmp_t, mountpoint; #, polydir type usr_t, file_type, mountpoint; type var_t, file_type, mountpoint; type var_lib_t, file_type, mountpoint; type var_lock_t, file_type, lockfile; type var_run_t, file_type, pidfile; type var_spool_t; type fs_t; type bdev_t; type binfmt_misc_fs_t; type capifs_t; type configfs_t; type eventpollfs_t; type futexfs_t; type hugetlbfs_t; type inotifyfs_t; type nfsd_fs_t; type ramfs_t; type romfs_t; type rpc_pipefs_t; type tmpfs_t; type autofs_t, noxattrfs; type cifs_t alias sambafs_t, noxattrfs; type dosfs_t, noxattrfs; type iso9660_t, filesystem_type, noxattrfs; type removable_t, noxattrfs; type nfs_t, filesystem_type, noxattrfs; type kernel_t, can_load_kernmodule; type debugfs_t; type proc_t, proc_type; type proc_kmsg_t, proc_type; type proc_kcore_t, proc_type; type proc_mdstat_t, proc_type; type proc_net_t, proc_type; type proc_xen_t, proc_type; type sysctl_t, sysctl_type; type sysctl_irq_t, sysctl_type; type sysctl_rpc_t, sysctl_type; type sysctl_fs_t, sysctl_type; type sysctl_kernel_t, sysctl_type; type sysctl_modprobe_t, sysctl_type; type sysctl_hotplug_t, sysctl_type; type sysctl_net_t, sysctl_type; type sysctl_net_unix_t, sysctl_type; type sysctl_vm_t, sysctl_type; type sysctl_dev_t, sysctl_type; type unlabeled_t; type auditd_exec_t; type crond_exec_t; type cupsd_exec_t; type getty_t; type init_t; type init_exec_t; type initrc_t; type initrc_exec_t; type login_exec_t; type sshd_exec_t; type su_exec_t; type udev_exec_t; type unconfined_t; type xdm_exec_t; type lvm_exec_t; type security_t; type bsdpty_device_t; type console_device_t; type devpts_t; type devtty_t; type ptmx_t; type tty_device_t, serial_device; type usbtty_device_t, serial_device; bool secure_mode false; bool secure_mode_insmod false; bool secure_mode_policyload false; bool allow_cvs_read_shadow false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool allow_ftpd_anon_write false; bool allow_gssd_read_tmp true; bool allow_httpd_anon_write false; bool allow_java_execstack false; bool allow_kerberos true; bool allow_rsync_anon_write false; bool allow_saslauthd_read_shadow false; bool allow_smbd_anon_write false; bool allow_ptrace false; bool allow_ypbind false; bool fcron_crond false; bool ftp_home_dir false; bool ftpd_is_daemon true; bool httpd_builtin_scripting true; bool httpd_can_network_connect false; bool httpd_can_network_connect_db false; bool httpd_can_network_relay false; bool httpd_enable_cgi true; bool httpd_enable_ftp_server false; bool httpd_enable_homedirs true; bool httpd_ssi_exec true; bool httpd_tty_comm false; bool httpd_unified true; bool named_write_master_zones false; bool nfs_export_all_rw true; bool nfs_export_all_ro true; bool pppd_can_insmod false; bool read_default_t true; bool run_ssh_inetd false; bool samba_enable_home_dirs false; bool spamassasin_can_network false; bool squid_connect_any false; bool ssh_sysadm_login false; bool stunnel_is_daemon false; bool use_nfs_home_dirs false; bool use_samba_home_dirs false; bool user_ping true; bool spamd_enable_home_dirs true; allow bin_t fs_t:filesystem associate; allow bin_t noxattrfs:filesystem associate; typeattribute bin_t file_type; allow sbin_t fs_t:filesystem associate; allow sbin_t noxattrfs:filesystem associate; typeattribute sbin_t file_type; allow ls_exec_t fs_t:filesystem associate; allow ls_exec_t noxattrfs:filesystem associate; typeattribute ls_exec_t file_type; typeattribute ls_exec_t entry_type; allow shell_exec_t fs_t:filesystem associate; allow shell_exec_t noxattrfs:filesystem associate; typeattribute shell_exec_t file_type; allow chroot_exec_t fs_t:filesystem associate; allow chroot_exec_t noxattrfs:filesystem associate; typeattribute chroot_exec_t file_type; typeattribute ppp_device_t device_node; allow ppp_device_t fs_t:filesystem associate; allow ppp_device_t tmpfs_t:filesystem associate; allow ppp_device_t tmp_t:filesystem associate; typeattribute tun_tap_device_t device_node; allow tun_tap_device_t fs_t:filesystem associate; allow tun_tap_device_t tmpfs_t:filesystem associate; allow tun_tap_device_t tmp_t:filesystem associate; typeattribute auth_port_t reserved_port_type; typeattribute bgp_port_t reserved_port_type; typeattribute bgp_port_t reserved_port_type; typeattribute comsat_port_t reserved_port_type; typeattribute dhcpc_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dns_port_t reserved_port_type; typeattribute dns_port_t reserved_port_type; typeattribute fingerd_port_t reserved_port_type; typeattribute ftp_data_port_t reserved_port_type; typeattribute ftp_port_t reserved_port_type; typeattribute gopher_port_t reserved_port_type; typeattribute gopher_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute innd_port_t reserved_port_type; typeattribute ipp_port_t reserved_port_type; typeattribute ipp_port_t reserved_port_type; typeattribute isakmp_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute ktalkd_port_t reserved_port_type; typeattribute ktalkd_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute ntp_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute portmap_port_t reserved_port_type; typeattribute portmap_port_t reserved_port_type; typeattribute printer_port_t reserved_port_type; typeattribute rlogind_port_t reserved_port_type; typeattribute rndc_port_t reserved_port_type; typeattribute router_port_t reserved_port_type; typeattribute rsh_port_t reserved_port_type; typeattribute rsync_port_t reserved_port_type; typeattribute rsync_port_t reserved_port_type; typeattribute smbd_port_t reserved_port_type; typeattribute smbd_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute spamd_port_t reserved_port_type; typeattribute ssh_port_t reserved_port_type; typeattribute swat_port_t reserved_port_type; typeattribute syslogd_port_t reserved_port_type; typeattribute telnetd_port_t reserved_port_type; typeattribute tftp_port_t reserved_port_type; typeattribute uucpd_port_t reserved_port_type; allow device_t tmpfs_t:filesystem associate; allow device_t fs_t:filesystem associate; allow device_t noxattrfs:filesystem associate; typeattribute device_t file_type; allow device_t fs_t:filesystem associate; allow device_t noxattrfs:filesystem associate; typeattribute device_t file_type; typeattribute device_t mountpoint; allow device_t tmp_t:filesystem associate; typeattribute agp_device_t device_node; allow agp_device_t fs_t:filesystem associate; allow agp_device_t tmpfs_t:filesystem associate; allow agp_device_t tmp_t:filesystem associate; typeattribute apm_bios_t device_node; allow apm_bios_t fs_t:filesystem associate; allow apm_bios_t tmpfs_t:filesystem associate; allow apm_bios_t tmp_t:filesystem associate; typeattribute cardmgr_dev_t device_node; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t tmpfs_t:filesystem associate; allow cardmgr_dev_t tmp_t:filesystem associate; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t noxattrfs:filesystem associate; typeattribute cardmgr_dev_t file_type; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t noxattrfs:filesystem associate; typeattribute cardmgr_dev_t file_type; typeattribute cardmgr_dev_t polymember; allow cardmgr_dev_t tmpfs_t:filesystem associate; typeattribute cardmgr_dev_t tmpfile; allow cardmgr_dev_t tmp_t:filesystem associate; typeattribute clock_device_t device_node; allow clock_device_t fs_t:filesystem associate; allow clock_device_t tmpfs_t:filesystem associate; allow clock_device_t tmp_t:filesystem associate; typeattribute cpu_device_t device_node; allow cpu_device_t fs_t:filesystem associate; allow cpu_device_t tmpfs_t:filesystem associate; allow cpu_device_t tmp_t:filesystem associate; typeattribute crypt_device_t device_node; allow crypt_device_t fs_t:filesystem associate; allow crypt_device_t tmpfs_t:filesystem associate; allow crypt_device_t tmp_t:filesystem associate; typeattribute dri_device_t device_node; allow dri_device_t fs_t:filesystem associate; allow dri_device_t tmpfs_t:filesystem associate; allow dri_device_t tmp_t:filesystem associate; typeattribute event_device_t device_node; allow event_device_t fs_t:filesystem associate; allow event_device_t tmpfs_t:filesystem associate; allow event_device_t tmp_t:filesystem associate; typeattribute framebuf_device_t device_node; allow framebuf_device_t fs_t:filesystem associate; allow framebuf_device_t tmpfs_t:filesystem associate; allow framebuf_device_t tmp_t:filesystem associate; typeattribute lvm_control_t device_node; allow lvm_control_t fs_t:filesystem associate; allow lvm_control_t tmpfs_t:filesystem associate; allow lvm_control_t tmp_t:filesystem associate; typeattribute memory_device_t device_node; allow memory_device_t fs_t:filesystem associate; allow memory_device_t tmpfs_t:filesystem associate; allow memory_device_t tmp_t:filesystem associate; neverallow ~memory_raw_read memory_device_t:{ chr_file blk_file } read; neverallow ~memory_raw_write memory_device_t:{ chr_file blk_file } { append write }; typeattribute misc_device_t device_node; allow misc_device_t fs_t:filesystem associate; allow misc_device_t tmpfs_t:filesystem associate; allow misc_device_t tmp_t:filesystem associate; typeattribute mouse_device_t device_node; allow mouse_device_t fs_t:filesystem associate; allow mouse_device_t tmpfs_t:filesystem associate; allow mouse_device_t tmp_t:filesystem associate; typeattribute mtrr_device_t device_node; allow mtrr_device_t fs_t:filesystem associate; allow mtrr_device_t tmpfs_t:filesystem associate; allow mtrr_device_t tmp_t:filesystem associate; typeattribute null_device_t device_node; allow null_device_t fs_t:filesystem associate; allow null_device_t tmpfs_t:filesystem associate; allow null_device_t tmp_t:filesystem associate; typeattribute null_device_t mlstrustedobject; typeattribute power_device_t device_node; allow power_device_t fs_t:filesystem associate; allow power_device_t tmpfs_t:filesystem associate; allow power_device_t tmp_t:filesystem associate; typeattribute printer_device_t device_node; allow printer_device_t fs_t:filesystem associate; allow printer_device_t tmpfs_t:filesystem associate; allow printer_device_t tmp_t:filesystem associate; typeattribute random_device_t device_node; allow random_device_t fs_t:filesystem associate; allow random_device_t tmpfs_t:filesystem associate; allow random_device_t tmp_t:filesystem associate; typeattribute scanner_device_t device_node; allow scanner_device_t fs_t:filesystem associate; allow scanner_device_t tmpfs_t:filesystem associate; allow scanner_device_t tmp_t:filesystem associate; typeattribute sound_device_t device_node; allow sound_device_t fs_t:filesystem associate; allow sound_device_t tmpfs_t:filesystem associate; allow sound_device_t tmp_t:filesystem associate; allow sysfs_t fs_t:filesystem associate; allow sysfs_t noxattrfs:filesystem associate; typeattribute sysfs_t file_type; typeattribute sysfs_t mountpoint; typeattribute sysfs_t filesystem_type; allow sysfs_t self:filesystem associate; typeattribute urandom_device_t device_node; allow urandom_device_t fs_t:filesystem associate; allow urandom_device_t tmpfs_t:filesystem associate; allow urandom_device_t tmp_t:filesystem associate; allow usbfs_t fs_t:filesystem associate; allow usbfs_t noxattrfs:filesystem associate; typeattribute usbfs_t file_type; typeattribute usbfs_t mountpoint; typeattribute usbfs_t filesystem_type; allow usbfs_t self:filesystem associate; typeattribute usbfs_t noxattrfs; typeattribute usb_device_t device_node; allow usb_device_t fs_t:filesystem associate; allow usb_device_t tmpfs_t:filesystem associate; allow usb_device_t tmp_t:filesystem associate; typeattribute v4l_device_t device_node; allow v4l_device_t fs_t:filesystem associate; allow v4l_device_t tmpfs_t:filesystem associate; allow v4l_device_t tmp_t:filesystem associate; typeattribute xserver_misc_device_t device_node; allow xserver_misc_device_t fs_t:filesystem associate; allow xserver_misc_device_t tmpfs_t:filesystem associate; allow xserver_misc_device_t tmp_t:filesystem associate; typeattribute zero_device_t device_node; allow zero_device_t fs_t:filesystem associate; allow zero_device_t tmpfs_t:filesystem associate; allow zero_device_t tmp_t:filesystem associate; typeattribute zero_device_t mlstrustedobject; allow xconsole_device_t fs_t:filesystem associate; allow xconsole_device_t noxattrfs:filesystem associate; typeattribute xconsole_device_t file_type; allow xconsole_device_t tmpfs_t:filesystem associate; allow xconsole_device_t tmp_t:filesystem associate; typeattribute devfs_control_t device_node; allow devfs_control_t fs_t:filesystem associate; allow devfs_control_t tmpfs_t:filesystem associate; allow devfs_control_t tmp_t:filesystem associate; neverallow domain ~domain:process { transition dyntransition }; neverallow { domain -set_curr_context } self:process setcurrent; neverallow { domain unlabeled_t } ~{ domain unlabeled_t }:process *; neverallow ~{ domain unlabeled_t } *:process *; allow file_type self:filesystem associate; allow boot_t fs_t:filesystem associate; allow boot_t noxattrfs:filesystem associate; typeattribute boot_t file_type; allow boot_t fs_t:filesystem associate; allow boot_t noxattrfs:filesystem associate; typeattribute boot_t file_type; typeattribute boot_t mountpoint; allow default_t fs_t:filesystem associate; allow default_t noxattrfs:filesystem associate; allow etc_t fs_t:filesystem associate; allow etc_t noxattrfs:filesystem associate; allow etc_runtime_t fs_t:filesystem associate; allow etc_runtime_t noxattrfs:filesystem associate; allow file_t fs_t:filesystem associate; allow file_t noxattrfs:filesystem associate; allow kernel_t file_t:dir mounton; allow home_root_t fs_t:filesystem associate; allow home_root_t noxattrfs:filesystem associate; allow home_root_t fs_t:filesystem associate; allow home_root_t noxattrfs:filesystem associate; typeattribute home_root_t file_type; typeattribute home_root_t polyparent; allow lost_found_t fs_t:filesystem associate; allow lost_found_t noxattrfs:filesystem associate; allow mnt_t fs_t:filesystem associate; allow mnt_t noxattrfs:filesystem associate; allow modules_object_t fs_t:filesystem associate; allow modules_object_t noxattrfs:filesystem associate; typeattribute modules_object_t file_type; allow no_access_t fs_t:filesystem associate; allow no_access_t noxattrfs:filesystem associate; allow poly_t fs_t:filesystem associate; allow poly_t noxattrfs:filesystem associate; allow readable_t fs_t:filesystem associate; allow readable_t noxattrfs:filesystem associate; allow root_t fs_t:filesystem associate; allow root_t noxattrfs:filesystem associate; allow root_t fs_t:filesystem associate; allow root_t noxattrfs:filesystem associate; typeattribute root_t file_type; typeattribute root_t polyparent; allow kernel_t root_t:dir mounton; allow src_t fs_t:filesystem associate; allow src_t noxattrfs:filesystem associate; allow system_map_t fs_t:filesystem associate; allow system_map_t noxattrfs:filesystem associate; typeattribute system_map_t file_type; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; typeattribute tmp_t polymember; allow tmp_t tmpfs_t:filesystem associate; typeattribute tmp_t tmpfile; allow tmp_t tmp_t:filesystem associate; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; typeattribute tmp_t polyparent; allow usr_t fs_t:filesystem associate; allow usr_t noxattrfs:filesystem associate; allow var_t fs_t:filesystem associate; allow var_t noxattrfs:filesystem associate; allow var_lib_t fs_t:filesystem associate; allow var_lib_t noxattrfs:filesystem associate; allow var_lock_t fs_t:filesystem associate; allow var_lock_t noxattrfs:filesystem associate; allow var_run_t fs_t:filesystem associate; allow var_run_t noxattrfs:filesystem associate; allow var_spool_t fs_t:filesystem associate; allow var_spool_t noxattrfs:filesystem associate; typeattribute var_spool_t file_type; allow var_spool_t fs_t:filesystem associate; allow var_spool_t noxattrfs:filesystem associate; typeattribute var_spool_t file_type; typeattribute var_spool_t polymember; allow var_spool_t tmpfs_t:filesystem associate; typeattribute var_spool_t tmpfile; allow var_spool_t tmp_t:filesystem associate; typeattribute fs_t filesystem_type; allow fs_t self:filesystem associate; typeattribute bdev_t filesystem_type; allow bdev_t self:filesystem associate; typeattribute binfmt_misc_fs_t filesystem_type; allow binfmt_misc_fs_t self:filesystem associate; allow binfmt_misc_fs_t fs_t:filesystem associate; allow binfmt_misc_fs_t noxattrfs:filesystem associate; typeattribute binfmt_misc_fs_t file_type; typeattribute binfmt_misc_fs_t mountpoint; typeattribute capifs_t filesystem_type; allow capifs_t self:filesystem associate; typeattribute configfs_t filesystem_type; allow configfs_t self:filesystem associate; typeattribute eventpollfs_t filesystem_type; allow eventpollfs_t self:filesystem associate; typeattribute futexfs_t filesystem_type; allow futexfs_t self:filesystem associate; typeattribute hugetlbfs_t filesystem_type; allow hugetlbfs_t self:filesystem associate; allow hugetlbfs_t fs_t:filesystem associate; allow hugetlbfs_t noxattrfs:filesystem associate; typeattribute hugetlbfs_t file_type; typeattribute hugetlbfs_t mountpoint; typeattribute inotifyfs_t filesystem_type; allow inotifyfs_t self:filesystem associate; typeattribute nfsd_fs_t filesystem_type; allow nfsd_fs_t self:filesystem associate; typeattribute ramfs_t filesystem_type; allow ramfs_t self:filesystem associate; typeattribute romfs_t filesystem_type; allow romfs_t self:filesystem associate; typeattribute rpc_pipefs_t filesystem_type; allow rpc_pipefs_t self:filesystem associate; typeattribute tmpfs_t filesystem_type; allow tmpfs_t self:filesystem associate; allow tmpfs_t fs_t:filesystem associate; allow tmpfs_t noxattrfs:filesystem associate; typeattribute tmpfs_t file_type; allow tmpfs_t fs_t:filesystem associate; allow tmpfs_t noxattrfs:filesystem associate; typeattribute tmpfs_t file_type; typeattribute tmpfs_t mountpoint; allow tmpfs_t noxattrfs:filesystem associate; typeattribute autofs_t filesystem_type; allow autofs_t self:filesystem associate; allow autofs_t fs_t:filesystem associate; allow autofs_t noxattrfs:filesystem associate; typeattribute autofs_t file_type; typeattribute autofs_t mountpoint; typeattribute cifs_t filesystem_type; allow cifs_t self:filesystem associate; typeattribute dosfs_t filesystem_type; allow dosfs_t self:filesystem associate; allow dosfs_t fs_t:filesystem associate; typeattribute iso9660_t filesystem_type; allow iso9660_t self:filesystem associate; allow removable_t noxattrfs:filesystem associate; typeattribute removable_t filesystem_type; allow removable_t self:filesystem associate; allow removable_t fs_t:filesystem associate; allow removable_t noxattrfs:filesystem associate; typeattribute removable_t file_type; typeattribute removable_t usercanread; typeattribute nfs_t filesystem_type; allow nfs_t self:filesystem associate; allow nfs_t fs_t:filesystem associate; allow nfs_t noxattrfs:filesystem associate; typeattribute nfs_t file_type; typeattribute nfs_t mountpoint; neverallow ~can_load_kernmodule self:capability sys_module; role system_r; role sysadm_r; role staff_r; role user_r; role secadm_r; typeattribute kernel_t domain; allow kernel_t self:dir { read getattr lock search ioctl }; allow kernel_t self:lnk_file { read getattr lock ioctl }; allow kernel_t self:file { getattr read write append ioctl lock }; allow kernel_t self:process { fork sigchld }; role secadm_r types kernel_t; role sysadm_r types kernel_t; role user_r types kernel_t; role staff_r types kernel_t; typeattribute kernel_t privrangetrans; role system_r types kernel_t; typeattribute debugfs_t filesystem_type; allow debugfs_t self:filesystem associate; allow debugfs_t self:filesystem associate; allow proc_t fs_t:filesystem associate; allow proc_t noxattrfs:filesystem associate; typeattribute proc_t file_type; typeattribute proc_t mountpoint; typeattribute proc_t filesystem_type; allow proc_t self:filesystem associate; neverallow ~can_receive_kernel_messages proc_kmsg_t:file ~getattr; neverallow { domain -kern_unconfined } proc_kcore_t:file ~getattr; allow sysctl_t fs_t:filesystem associate; allow sysctl_t noxattrfs:filesystem associate; typeattribute sysctl_t file_type; typeattribute sysctl_t mountpoint; allow sysctl_fs_t fs_t:filesystem associate; allow sysctl_fs_t noxattrfs:filesystem associate; typeattribute sysctl_fs_t file_type; typeattribute sysctl_fs_t mountpoint; allow kernel_t self:capability *; allow kernel_t unlabeled_t:dir mounton; allow kernel_t self:process ~{ ptrace setcurrent setexec setfscreate setrlimit execmem execstack execheap }; allow kernel_t self:shm { associate getattr setattr create destroy read write lock unix_read unix_write }; allow kernel_t self:sem { associate getattr setattr create destroy read write unix_read unix_write }; allow kernel_t self:msg { send receive }; allow kernel_t self:msgq { associate getattr setattr create destroy read write enqueue unix_read unix_write }; allow kernel_t self:unix_dgram_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } }; allow kernel_t self:unix_stream_socket { { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } } listen accept }; allow kernel_t self:unix_dgram_socket sendto; allow kernel_t self:unix_stream_socket connectto; allow kernel_t self:fifo_file { getattr read write append ioctl lock }; allow kernel_t self:sock_file { read getattr lock ioctl }; allow kernel_t self:fd use; allow kernel_t proc_t:dir { read getattr lock search ioctl }; allow kernel_t proc_t:{ lnk_file file } { read getattr lock ioctl }; allow kernel_t proc_net_t:dir { read getattr lock search ioctl }; allow kernel_t proc_net_t:file { read getattr lock ioctl }; allow kernel_t proc_mdstat_t:file { read getattr lock ioctl }; allow kernel_t proc_kcore_t:file getattr; allow kernel_t proc_kmsg_t:file getattr; allow kernel_t sysctl_t:dir { read getattr lock search ioctl }; allow kernel_t sysctl_kernel_t:dir { read getattr lock search ioctl }; allow kernel_t sysctl_kernel_t:file { read getattr lock ioctl }; allow kernel_t unlabeled_t:fifo_file { getattr read write append ioctl lock }; allow kernel_t unlabeled_t:association { sendto recvfrom }; allow kernel_t netif_type:netif rawip_send; allow kernel_t netif_type:netif rawip_recv; allow kernel_t node_type:node rawip_send; allow kernel_t node_type:node rawip_recv; allow kernel_t netif_t:netif rawip_send; allow kernel_t netif_type:netif { tcp_send tcp_recv }; allow kernel_t node_type:node { tcp_send tcp_recv }; allow kernel_t node_t:node rawip_send; allow kernel_t multicast_node_t:node rawip_send; allow kernel_t sysfs_t:dir { read getattr lock search ioctl }; allow kernel_t sysfs_t:{ file lnk_file } { read getattr lock ioctl }; allow kernel_t usbfs_t:dir search; allow kernel_t filesystem_type:filesystem mount; allow kernel_t security_t:dir { read search getattr }; allow kernel_t security_t:file { getattr read write }; typeattribute kernel_t can_load_policy; if(!secure_mode_policyload) { allow kernel_t security_t:security load_policy; auditallow kernel_t security_t:security load_policy; } allow kernel_t device_t:dir { read getattr lock search ioctl }; allow kernel_t device_t:lnk_file { getattr read }; allow kernel_t console_device_t:chr_file { getattr read write append ioctl lock }; allow kernel_t bin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:lnk_file { read getattr lock ioctl }; allow kernel_t shell_exec_t:file { { read getattr lock execute ioctl } execute_no_trans }; allow kernel_t sbin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:lnk_file { read getattr lock ioctl }; allow kernel_t bin_t:file { { read getattr lock execute ioctl } execute_no_trans }; allow kernel_t domain:process signal; allow kernel_t proc_t:dir search; allow kernel_t domain:dir search; allow kernel_t root_t:dir { read getattr lock search ioctl }; allow kernel_t root_t:lnk_file { read getattr lock ioctl }; allow kernel_t etc_t:dir { read getattr lock search ioctl }; allow kernel_t home_root_t:dir { read getattr lock search ioctl }; allow kernel_t usr_t:dir { read getattr lock search ioctl }; allow kernel_t usr_t:{ file lnk_file } { read getattr lock ioctl }; typeattribute kernel_t mlsprocread; typeattribute kernel_t mlsprocwrite; allow kernel_t self:capability *; allow kernel_t self:fifo_file { create ioctl read getattr lock write setattr append link unlink rename }; allow kernel_t self:process transition; allow kernel_t self:file { getattr read write append ioctl lock }; allow kernel_t self:nscd *; allow kernel_t self:dbus *; allow kernel_t self:passwd *; allow kernel_t proc_type:{ dir file } *; allow kernel_t sysctl_t:{ dir file } *; allow kernel_t kernel_t:system *; allow kernel_t unlabeled_t:{ dir file lnk_file sock_file fifo_file chr_file blk_file } *; allow kernel_t unlabeled_t:filesystem *; allow kernel_t unlabeled_t:association *; typeattribute kernel_t can_load_kernmodule, can_receive_kernel_messages; typeattribute kernel_t kern_unconfined; allow kernel_t { proc_t proc_net_t }:dir search; allow kernel_t sysctl_type:dir { read getattr lock search ioctl }; allow kernel_t sysctl_type:file { { getattr read write append ioctl lock } setattr }; allow kernel_t node_type:node *; allow kernel_t netif_type:netif *; allow kernel_t port_type:tcp_socket { send_msg recv_msg name_connect }; allow kernel_t port_type:udp_socket { send_msg recv_msg }; allow kernel_t port_type:{ tcp_socket udp_socket rawip_socket } name_bind; allow kernel_t node_type:{ tcp_socket udp_socket rawip_socket } node_bind; allow kernel_t unlabeled_t:association { sendto recvfrom }; allow kernel_t device_node:{ chr_file blk_file } *; allow kernel_t mtrr_device_t:{ dir file } *; allow kernel_t self:capability sys_rawio; typeattribute kernel_t memory_raw_write, memory_raw_read; typeattribute kernel_t unconfined_domain_type; typeattribute kernel_t can_change_process_identity; typeattribute kernel_t can_change_process_role; typeattribute kernel_t can_change_object_identity; typeattribute kernel_t set_curr_context; allow kernel_t domain:{ { tcp_socket udp_socket rawip_socket netlink_socket packet_socket unix_stream_socket unix_dgram_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket } socket key_socket } *; allow kernel_t domain:fd use; allow kernel_t domain:fifo_file { getattr read write append ioctl lock }; allow kernel_t domain:process ~{ transition dyntransition execmem execstack execheap }; allow kernel_t domain:{ sem msgq shm } *; allow kernel_t domain:msg { send receive }; allow kernel_t domain:dir { read getattr lock search ioctl }; allow kernel_t domain:file { read getattr lock ioctl }; allow kernel_t domain:lnk_file { read getattr lock ioctl }; dontaudit kernel_t domain:dir { read getattr lock search ioctl }; dontaudit kernel_t domain:lnk_file { read getattr lock ioctl }; dontaudit kernel_t domain:file { read getattr lock ioctl }; dontaudit kernel_t domain:sock_file { read getattr lock ioctl }; dontaudit kernel_t domain:fifo_file { read getattr lock ioctl }; allow kernel_t file_type:{ file chr_file } ~execmod; allow kernel_t file_type:{ dir lnk_file sock_file fifo_file blk_file } *; allow kernel_t file_type:filesystem *; allow kernel_t file_type:{ unix_stream_socket unix_dgram_socket } name_bind; if (allow_execmod) { allow kernel_t file_type:file execmod; } allow kernel_t filesystem_type:filesystem *; allow kernel_t filesystem_type:{ dir file lnk_file sock_file fifo_file chr_file blk_file } *; allow kernel_t security_t:dir { getattr search read }; allow kernel_t security_t:file { getattr read write }; typeattribute kernel_t can_load_policy, can_setenforce, can_setsecparam; if(!secure_mode_policyload) { allow kernel_t security_t:security *; auditallow kernel_t security_t:security { load_policy setenforce setbool }; } if (allow_execheap) { allow kernel_t self:process execheap; } if (allow_execmem) { allow kernel_t self:process execmem; } if (allow_execmem && allow_execstack) { allow kernel_t self:process execstack; auditallow kernel_t self:process execstack; } else { } if (allow_execheap) { auditallow kernel_t self:process execheap; } if (allow_execmem) { auditallow kernel_t self:process execmem; } if (read_default_t) { allow kernel_t default_t:dir { read getattr lock search ioctl }; allow kernel_t default_t:file { read getattr lock ioctl }; allow kernel_t default_t:lnk_file { read getattr lock ioctl }; allow kernel_t default_t:sock_file { read getattr lock ioctl }; allow kernel_t default_t:fifo_file { read getattr lock ioctl }; } allow unlabeled_t self:filesystem associate; range_transition getty_t login_exec_t s0 - s0:c0.c255; range_transition init_t xdm_exec_t s0 - s0:c0.c255; range_transition initrc_t crond_exec_t s0 - s0:c0.c255; range_transition initrc_t cupsd_exec_t s0 - s0:c0.c255; range_transition initrc_t sshd_exec_t s0 - s0:c0.c255; range_transition initrc_t udev_exec_t s0 - s0:c0.c255; range_transition initrc_t xdm_exec_t s0 - s0:c0.c255; range_transition kernel_t udev_exec_t s0 - s0:c0.c255; range_transition unconfined_t su_exec_t s0 - s0:c0.c255; range_transition unconfined_t initrc_exec_t s0; typeattribute security_t filesystem_type; allow security_t self:filesystem associate; typeattribute security_t mlstrustedobject; neverallow ~can_load_policy security_t:security load_policy; neverallow ~can_setenforce security_t:security setenforce; neverallow ~can_setsecparam security_t:security setsecparam; typeattribute bsdpty_device_t device_node; allow bsdpty_device_t fs_t:filesystem associate; allow bsdpty_device_t tmpfs_t:filesystem associate; allow bsdpty_device_t tmp_t:filesystem associate; typeattribute console_device_t device_node; allow console_device_t fs_t:filesystem associate; allow console_device_t tmpfs_t:filesystem associate; allow console_device_t tmp_t:filesystem associate; allow devpts_t fs_t:filesystem associate; allow devpts_t noxattrfs:filesystem associate; typeattribute devpts_t file_type; typeattribute devpts_t mountpoint; allow devpts_t tmpfs_t:filesystem associate; allow devpts_t tmp_t:filesystem associate; typeattribute devpts_t filesystem_type; allow devpts_t self:filesystem associate; typeattribute devpts_t ttynode, ptynode; typeattribute devtty_t device_node; allow devtty_t fs_t:filesystem associate; allow devtty_t tmpfs_t:filesystem associate; allow devtty_t tmp_t:filesystem associate; typeattribute devtty_t mlstrustedobject; typeattribute ptmx_t device_node; allow ptmx_t fs_t:filesystem associate; allow ptmx_t tmpfs_t:filesystem associate; allow ptmx_t tmp_t:filesystem associate; typeattribute ptmx_t mlstrustedobject; typeattribute tty_device_t device_node; allow tty_device_t fs_t:filesystem associate; allow tty_device_t tmpfs_t:filesystem associate; allow tty_device_t tmp_t:filesystem associate; typeattribute tty_device_t ttynode; typeattribute usbtty_device_t device_node; allow usbtty_device_t fs_t:filesystem associate; allow usbtty_device_t tmpfs_t:filesystem associate; allow usbtty_device_t tmp_t:filesystem associate; user system_u roles { system_r } level s0 range s0 - s0:c0.c255; user user_u roles { user_r sysadm_r system_r } level s0 range s0 - s0:c0.c255; user root roles { user_r sysadm_r system_r } level s0 range s0 - s0:c0.c255; constrain process transition ( u1 == u2 or t1 == can_change_process_identity ); constrain process transition ( r1 == r2 or t1 == can_change_process_role ); constrain process dyntransition ( u1 == u2 and r1 == r2 ); constrain { dir file lnk_file sock_file fifo_file chr_file blk_file } { create relabelto relabelfrom } ( u1 == u2 or t1 == can_change_object_identity ); constrain { tcp_socket udp_socket rawip_socket netlink_socket packet_socket unix_stream_socket unix_dgram_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket } { create relabelto relabelfrom } ( u1 == u2 or t1 == can_change_object_identity ); sid port system_u:object_r:port_t:s0 sid node system_u:object_r:node_t:s0 sid netif system_u:object_r:netif_t:s0 sid devnull system_u:object_r:null_device_t:s0 sid file system_u:object_r:file_t:s0 sid fs system_u:object_r:fs_t:s0 sid kernel system_u:system_r:kernel_t:s0 sid sysctl system_u:object_r:sysctl_t:s0 sid unlabeled system_u:object_r:unlabeled_t:s0 sid any_socket system_u:object_r:unlabeled_t:s0 sid file_labels system_u:object_r:unlabeled_t:s0 sid icmp_socket system_u:object_r:unlabeled_t:s0 sid igmp_packet system_u:object_r:unlabeled_t:s0 sid init system_u:object_r:unlabeled_t:s0 sid kmod system_u:object_r:unlabeled_t:s0 sid netmsg system_u:object_r:unlabeled_t:s0 sid policy system_u:object_r:unlabeled_t:s0 sid scmp_packet system_u:object_r:unlabeled_t:s0 sid sysctl_modprobe system_u:object_r:unlabeled_t:s0 sid sysctl_fs system_u:object_r:unlabeled_t:s0 sid sysctl_kernel system_u:object_r:unlabeled_t:s0 sid sysctl_net system_u:object_r:unlabeled_t:s0 sid sysctl_net_unix system_u:object_r:unlabeled_t:s0 sid sysctl_vm system_u:object_r:unlabeled_t:s0 sid sysctl_dev system_u:object_r:unlabeled_t:s0 sid tcp_socket system_u:object_r:unlabeled_t:s0 sid security system_u:object_r:security_t:s0 fs_use_xattr ext2 system_u:object_r:fs_t:s0; fs_use_xattr ext3 system_u:object_r:fs_t:s0; fs_use_xattr gfs system_u:object_r:fs_t:s0; fs_use_xattr jfs system_u:object_r:fs_t:s0; fs_use_xattr reiserfs system_u:object_r:fs_t:s0; fs_use_xattr xfs system_u:object_r:fs_t:s0; fs_use_task pipefs system_u:object_r:fs_t:s0; fs_use_task sockfs system_u:object_r:fs_t:s0; fs_use_trans mqueue system_u:object_r:tmpfs_t:s0; fs_use_trans shm system_u:object_r:tmpfs_t:s0; fs_use_trans tmpfs system_u:object_r:tmpfs_t:s0; fs_use_trans devpts system_u:object_r:devpts_t:s0; genfscon proc /mtrr system_u:object_r:mtrr_device_t:s0 genfscon sysfs / system_u:object_r:sysfs_t:s0 genfscon usbfs / system_u:object_r:usbfs_t:s0 genfscon usbdevfs / system_u:object_r:usbfs_t:s0 genfscon rootfs / system_u:object_r:root_t:s0 genfscon bdev / system_u:object_r:bdev_t:s0 genfscon binfmt_misc / system_u:object_r:binfmt_misc_fs_t:s0 genfscon capifs / system_u:object_r:capifs_t:s0 genfscon configfs / system_u:object_r:configfs_t:s0 genfscon eventpollfs / system_u:object_r:eventpollfs_t:s0 genfscon futexfs / system_u:object_r:futexfs_t:s0 genfscon hugetlbfs / system_u:object_r:hugetlbfs_t:s0 genfscon inotifyfs / system_u:object_r:inotifyfs_t:s0 genfscon nfsd / system_u:object_r:nfsd_fs_t:s0 genfscon ramfs / system_u:object_r:ramfs_t:s0 genfscon romfs / system_u:object_r:romfs_t:s0 genfscon cramfs / system_u:object_r:romfs_t:s0 genfscon rpc_pipefs / system_u:object_r:rpc_pipefs_t:s0 genfscon autofs / system_u:object_r:autofs_t:s0 genfscon automount / system_u:object_r:autofs_t:s0 genfscon cifs / system_u:object_r:cifs_t:s0 genfscon smbfs / system_u:object_r:cifs_t:s0 genfscon fat / system_u:object_r:dosfs_t:s0 genfscon msdos / system_u:object_r:dosfs_t:s0 genfscon ntfs / system_u:object_r:dosfs_t:s0 genfscon vfat / system_u:object_r:dosfs_t:s0 genfscon iso9660 / system_u:object_r:iso9660_t:s0 genfscon udf / system_u:object_r:iso9660_t:s0 genfscon nfs / system_u:object_r:nfs_t:s0 genfscon nfs4 / system_u:object_r:nfs_t:s0 genfscon afs / system_u:object_r:nfs_t:s0 genfscon hfsplus / system_u:object_r:nfs_t:s0 genfscon debugfs / system_u:object_r:debugfs_t:s0 genfscon proc / system_u:object_r:proc_t:s0 genfscon proc /sysvipc system_u:object_r:proc_t:s0 genfscon proc /kmsg system_u:object_r:proc_kmsg_t:s0 genfscon proc /kcore system_u:object_r:proc_kcore_t:s0 genfscon proc /mdstat system_u:object_r:proc_mdstat_t:s0 genfscon proc /net system_u:object_r:proc_net_t:s0 genfscon proc /xen system_u:object_r:proc_xen_t:s0 genfscon proc /sys system_u:object_r:sysctl_t:s0 genfscon proc /irq system_u:object_r:sysctl_irq_t:s0 genfscon proc /net/rpc system_u:object_r:sysctl_rpc_t:s0 genfscon proc /sys/fs system_u:object_r:sysctl_fs_t:s0 genfscon proc /sys/kernel system_u:object_r:sysctl_kernel_t:s0 genfscon proc /sys/kernel/modprobe system_u:object_r:sysctl_modprobe_t:s0 genfscon proc /sys/kernel/hotplug system_u:object_r:sysctl_hotplug_t:s0 genfscon proc /sys/net system_u:object_r:sysctl_net_t:s0 genfscon proc /sys/net/unix system_u:object_r:sysctl_net_unix_t:s0 genfscon proc /sys/vm system_u:object_r:sysctl_vm_t:s0 genfscon proc /sys/dev system_u:object_r:sysctl_dev_t:s0 genfscon selinuxfs / system_u:object_r:security_t:s0 portcon udp 7007 system_u:object_r:afs_bos_port_t:s0 portcon tcp 2040 system_u:object_r:afs_fs_port_t:s0 portcon udp 7000 system_u:object_r:afs_fs_port_t:s0 portcon udp 7005 system_u:object_r:afs_fs_port_t:s0 portcon udp 7004 system_u:object_r:afs_ka_port_t:s0 portcon udp 7002 system_u:object_r:afs_pt_port_t:s0 portcon udp 7003 system_u:object_r:afs_vl_port_t:s0 portcon udp 10080 system_u:object_r:amanda_port_t:s0 portcon tcp 10080 system_u:object_r:amanda_port_t:s0 portcon udp 10081 system_u:object_r:amanda_port_t:s0 portcon tcp 10081 system_u:object_r:amanda_port_t:s0 portcon tcp 10082 system_u:object_r:amanda_port_t:s0 portcon tcp 10083 system_u:object_r:amanda_port_t:s0 portcon tcp 10024 system_u:object_r:amavisd_recv_port_t:s0 portcon tcp 10025 system_u:object_r:amavisd_send_port_t:s0 portcon tcp 1720 system_u:object_r:asterisk_port_t:s0 portcon udp 2427 system_u:object_r:asterisk_port_t:s0 portcon udp 2727 system_u:object_r:asterisk_port_t:s0 portcon udp 4569 system_u:object_r:asterisk_port_t:s0 portcon udp 5060 system_u:object_r:asterisk_port_t:s0 portcon tcp 113 system_u:object_r:auth_port_t:s0 portcon tcp 179 system_u:object_r:bgp_port_t:s0 portcon udp 179 system_u:object_r:bgp_port_t:s0 portcon tcp 3310 system_u:object_r:clamd_port_t:s0 portcon udp 4041 system_u:object_r:clockspeed_port_t:s0 portcon udp 512 system_u:object_r:comsat_port_t:s0 portcon tcp 2401 system_u:object_r:cvs_port_t:s0 portcon udp 2401 system_u:object_r:cvs_port_t:s0 portcon udp 6276 system_u:object_r:dcc_port_t:s0 portcon udp 6277 system_u:object_r:dcc_port_t:s0 portcon tcp 1178 system_u:object_r:dbskkd_port_t:s0 portcon udp 68 system_u:object_r:dhcpc_port_t:s0 portcon udp 67 system_u:object_r:dhcpd_port_t:s0 portcon tcp 647 system_u:object_r:dhcpd_port_t:s0 portcon udp 647 system_u:object_r:dhcpd_port_t:s0 portcon tcp 847 system_u:object_r:dhcpd_port_t:s0 portcon udp 847 system_u:object_r:dhcpd_port_t:s0 portcon tcp 2628 system_u:object_r:dict_port_t:s0 portcon tcp 3632 system_u:object_r:distccd_port_t:s0 portcon udp 53 system_u:object_r:dns_port_t:s0 portcon tcp 53 system_u:object_r:dns_port_t:s0 portcon tcp 79 system_u:object_r:fingerd_port_t:s0 portcon tcp 20 system_u:object_r:ftp_data_port_t:s0 portcon tcp 21 system_u:object_r:ftp_port_t:s0 portcon udp 1718 system_u:object_r:gatekeeper_port_t:s0 portcon udp 1719 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 1721 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 7000 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 1213 system_u:object_r:giftd_port_t:s0 portcon tcp 70 system_u:object_r:gopher_port_t:s0 portcon udp 70 system_u:object_r:gopher_port_t:s0 portcon tcp 3128 system_u:object_r:http_cache_port_t:s0 portcon udp 3130 system_u:object_r:http_cache_port_t:s0 portcon tcp 8080 system_u:object_r:http_cache_port_t:s0 portcon tcp 8118 system_u:object_r:http_cache_port_t:s0 portcon tcp 80 system_u:object_r:http_port_t:s0 portcon tcp 443 system_u:object_r:http_port_t:s0 portcon tcp 488 system_u:object_r:http_port_t:s0 portcon tcp 8008 system_u:object_r:http_port_t:s0 portcon tcp 9050 system_u:object_r:http_port_t:s0 portcon tcp 5335 system_u:object_r:howl_port_t:s0 portcon udp 5353 system_u:object_r:howl_port_t:s0 portcon tcp 50000 system_u:object_r:hplip_port_t:s0 portcon tcp 50002 system_u:object_r:hplip_port_t:s0 portcon tcp 9010 system_u:object_r:i18n_input_port_t:s0 portcon tcp 5323 system_u:object_r:imaze_port_t:s0 portcon udp 5323 system_u:object_r:imaze_port_t:s0 portcon tcp 7 system_u:object_r:inetd_child_port_t:s0 portcon udp 7 system_u:object_r:inetd_child_port_t:s0 portcon tcp 9 system_u:object_r:inetd_child_port_t:s0 portcon udp 9 system_u:object_r:inetd_child_port_t:s0 portcon tcp 13 system_u:object_r:inetd_child_port_t:s0 portcon udp 13 system_u:object_r:inetd_child_port_t:s0 portcon tcp 19 system_u:object_r:inetd_child_port_t:s0 portcon udp 19 system_u:object_r:inetd_child_port_t:s0 portcon tcp 37 system_u:object_r:inetd_child_port_t:s0 portcon udp 37 system_u:object_r:inetd_child_port_t:s0 portcon tcp 512 system_u:object_r:inetd_child_port_t:s0 portcon tcp 543 system_u:object_r:inetd_child_port_t:s0 portcon tcp 544 system_u:object_r:inetd_child_port_t:s0 portcon tcp 891 system_u:object_r:inetd_child_port_t:s0 portcon udp 891 system_u:object_r:inetd_child_port_t:s0 portcon tcp 892 system_u:object_r:inetd_child_port_t:s0 portcon udp 892 system_u:object_r:inetd_child_port_t:s0 portcon tcp 2105 system_u:object_r:inetd_child_port_t:s0 portcon tcp 5666 system_u:object_r:inetd_child_port_t:s0 portcon tcp 119 system_u:object_r:innd_port_t:s0 portcon tcp 631 system_u:object_r:ipp_port_t:s0 portcon udp 631 system_u:object_r:ipp_port_t:s0 portcon tcp 6667 system_u:object_r:ircd_port_t:s0 portcon udp 500 system_u:object_r:isakmp_port_t:s0 portcon tcp 5222 system_u:object_r:jabber_client_port_t:s0 portcon tcp 5223 system_u:object_r:jabber_client_port_t:s0 portcon tcp 5269 system_u:object_r:jabber_interserver_port_t:s0 portcon tcp 464 system_u:object_r:kerberos_admin_port_t:s0 portcon udp 464 system_u:object_r:kerberos_admin_port_t:s0 portcon tcp 749 system_u:object_r:kerberos_admin_port_t:s0 portcon tcp 4444 system_u:object_r:kerberos_master_port_t:s0 portcon udp 4444 system_u:object_r:kerberos_master_port_t:s0 portcon tcp 88 system_u:object_r:kerberos_port_t:s0 portcon udp 88 system_u:object_r:kerberos_port_t:s0 portcon tcp 750 system_u:object_r:kerberos_port_t:s0 portcon udp 750 system_u:object_r:kerberos_port_t:s0 portcon udp 517 system_u:object_r:ktalkd_port_t:s0 portcon udp 518 system_u:object_r:ktalkd_port_t:s0 portcon tcp 389 system_u:object_r:ldap_port_t:s0 portcon udp 389 system_u:object_r:ldap_port_t:s0 portcon tcp 636 system_u:object_r:ldap_port_t:s0 portcon udp 636 system_u:object_r:ldap_port_t:s0 portcon tcp 2000 system_u:object_r:mail_port_t:s0 portcon tcp 1234 system_u:object_r:monopd_port_t:s0 portcon tcp 3306 system_u:object_r:mysqld_port_t:s0 portcon tcp 1241 system_u:object_r:nessus_port_t:s0 portcon udp 137 system_u:object_r:nmbd_port_t:s0 portcon udp 138 system_u:object_r:nmbd_port_t:s0 portcon udp 139 system_u:object_r:nmbd_port_t:s0 portcon udp 123 system_u:object_r:ntp_port_t:s0 portcon udp 5000 system_u:object_r:openvpn_port_t:s0 portcon tcp 5988 system_u:object_r:pegasus_http_port_t:s0 portcon tcp 5989 system_u:object_r:pegasus_https_port_t:s0 portcon tcp 106 system_u:object_r:pop_port_t:s0 portcon tcp 109 system_u:object_r:pop_port_t:s0 portcon tcp 110 system_u:object_r:pop_port_t:s0 portcon tcp 143 system_u:object_r:pop_port_t:s0 portcon tcp 220 system_u:object_r:pop_port_t:s0 portcon tcp 993 system_u:object_r:pop_port_t:s0 portcon tcp 995 system_u:object_r:pop_port_t:s0 portcon tcp 1109 system_u:object_r:pop_port_t:s0 portcon udp 111 system_u:object_r:portmap_port_t:s0 portcon tcp 111 system_u:object_r:portmap_port_t:s0 portcon tcp 5432 system_u:object_r:postgresql_port_t:s0 portcon tcp 60000 system_u:object_r:postgrey_port_t:s0 portcon tcp 515 system_u:object_r:printer_port_t:s0 portcon tcp 5703 system_u:object_r:ptal_port_t:s0 portcon udp 4011 system_u:object_r:pxe_port_t:s0 portcon udp 24441 system_u:object_r:pyzor_port_t:s0 portcon udp 1646 system_u:object_r:radacct_port_t:s0 portcon udp 1813 system_u:object_r:radacct_port_t:s0 portcon udp 1645 system_u:object_r:radius_port_t:s0 portcon udp 1812 system_u:object_r:radius_port_t:s0 portcon tcp 2703 system_u:object_r:razor_port_t:s0 portcon tcp 513 system_u:object_r:rlogind_port_t:s0 portcon tcp 953 system_u:object_r:rndc_port_t:s0 portcon udp 520 system_u:object_r:router_port_t:s0 portcon tcp 514 system_u:object_r:rsh_port_t:s0 portcon tcp 873 system_u:object_r:rsync_port_t:s0 portcon udp 873 system_u:object_r:rsync_port_t:s0 portcon tcp 137-139 system_u:object_r:smbd_port_t:s0 portcon tcp 445 system_u:object_r:smbd_port_t:s0 portcon tcp 25 system_u:object_r:smtp_port_t:s0 portcon tcp 465 system_u:object_r:smtp_port_t:s0 portcon tcp 587 system_u:object_r:smtp_port_t:s0 portcon udp 161 system_u:object_r:snmp_port_t:s0 portcon udp 162 system_u:object_r:snmp_port_t:s0 portcon tcp 199 system_u:object_r:snmp_port_t:s0 portcon tcp 783 system_u:object_r:spamd_port_t:s0 portcon tcp 22 system_u:object_r:ssh_port_t:s0 portcon tcp 8000 system_u:object_r:soundd_port_t:s0 portcon tcp 9433 system_u:object_r:soundd_port_t:s0 portcon tcp 901 system_u:object_r:swat_port_t:s0 portcon udp 514 system_u:object_r:syslogd_port_t:s0 portcon tcp 23 system_u:object_r:telnetd_port_t:s0 portcon udp 69 system_u:object_r:tftp_port_t:s0 portcon tcp 8081 system_u:object_r:transproxy_port_t:s0 portcon tcp 540 system_u:object_r:uucpd_port_t:s0 portcon tcp 5900 system_u:object_r:vnc_port_t:s0 portcon tcp 6001 system_u:object_r:xserver_port_t:s0 portcon tcp 6002 system_u:object_r:xserver_port_t:s0 portcon tcp 6003 system_u:object_r:xserver_port_t:s0 portcon tcp 6004 system_u:object_r:xserver_port_t:s0 portcon tcp 6005 system_u:object_r:xserver_port_t:s0 portcon tcp 6006 system_u:object_r:xserver_port_t:s0 portcon tcp 6007 system_u:object_r:xserver_port_t:s0 portcon tcp 6008 system_u:object_r:xserver_port_t:s0 portcon tcp 6009 system_u:object_r:xserver_port_t:s0 portcon tcp 6010 system_u:object_r:xserver_port_t:s0 portcon tcp 6011 system_u:object_r:xserver_port_t:s0 portcon tcp 6012 system_u:object_r:xserver_port_t:s0 portcon tcp 6013 system_u:object_r:xserver_port_t:s0 portcon tcp 6014 system_u:object_r:xserver_port_t:s0 portcon tcp 6015 system_u:object_r:xserver_port_t:s0 portcon tcp 6016 system_u:object_r:xserver_port_t:s0 portcon tcp 6017 system_u:object_r:xserver_port_t:s0 portcon tcp 6018 system_u:object_r:xserver_port_t:s0 portcon tcp 6019 system_u:object_r:xserver_port_t:s0 portcon tcp 8002 system_u:object_r:xen_port_t:s0 portcon tcp 2601 system_u:object_r:zebra_port_t:s0 portcon tcp 8021 system_u:object_r:zope_port_t:s0 portcon tcp 1-1023 system_u:object_r:reserved_port_t:s0 portcon udp 1-1023 system_u:object_r:reserved_port_t:s0 nodecon :: ffff:ffff:ffff:ffff:ffff:ffff:: system_u:object_r:compat_ipv4_node_t:s0 nodecon 0.0.0.0 255.255.255.255 system_u:object_r:inaddr_any_node_t:s0 nodecon fe80:: ffff:ffff:ffff:ffff:: system_u:object_r:link_local_node_t:s0 nodecon 127.0.0.1 255.255.255.255 system_u:object_r:lo_node_t:s0 nodecon ::ffff:0000:0000 ffff:ffff:ffff:ffff:ffff:ffff:: system_u:object_r:mapped_ipv4_node_t:s0 nodecon ff00:: ff00:: system_u:object_r:multicast_node_t:s0 nodecon fec0:: ffc0:: system_u:object_r:site_local_node_t:s0 nodecon :: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system_u:object_r:unspec_node_t:s0 libsepol/tests/policies/test-deps/0040755 0000000 0000000 00000000000 13756670065 016321 5ustar000000000 0000000 libsepol/tests/policies/test-deps/base-metreq.conf0100644 0000000 0000000 00000016440 13756670065 021377 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; # Make this decl easy to find type base_global_decl_t; # Actually used in module tests type type_req_t; attribute attr_req; bool bool_req false; role role_req_r; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:net_foo_t, s0) libsepol/tests/policies/test-deps/base-notmetreq.conf0100644 0000000 0000000 00000016174 13756670065 022124 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class msgq inherits ipc { enqueue } class msg { send } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:net_foo_t, s0) libsepol/tests/policies/test-deps/modreq-attr-global.conf0100644 0000000 0000000 00000000156 13756670065 022664 0ustar000000000 0000000 module modreq_attr_global 1.0; require { attribute attr_req; } type mod_global_t; type new_t, attr_req; libsepol/tests/policies/test-deps/modreq-attr-opt.conf0100644 0000000 0000000 00000000264 13756670065 022226 0ustar000000000 0000000 module modreq_attr_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { attribute attr_req; } type mod_opt_t; type new_t, attr_req; } libsepol/tests/policies/test-deps/modreq-bool-global.conf0100644 0000000 0000000 00000000273 13756670065 022645 0ustar000000000 0000000 module modreq_bool_global 1.0; require { bool bool_req; class file { read write }; } type mod_global_t; type a_t; type b_t; if (bool_req) { allow a_t b_t : file { read write }; } libsepol/tests/policies/test-deps/modreq-bool-opt.conf0100644 0000000 0000000 00000000354 13756670065 022207 0ustar000000000 0000000 module modreq_bool_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { bool bool_req; } type a_t; type b_t; type mod_opt_t; if (bool_req) { allow a_t b_t : file { read write }; } } libsepol/tests/policies/test-deps/modreq-obj-global.conf0100644 0000000 0000000 00000000266 13756670065 022466 0ustar000000000 0000000 module modreq_obj_global 1.0; require { class sem { create destroy }; } type mod_global_t; type mod_foo_t; type mod_bar_t; allow mod_foo_t mod_bar_t : sem { create destroy }; libsepol/tests/policies/test-deps/modreq-obj-opt.conf0100644 0000000 0000000 00000000374 13756670065 022030 0ustar000000000 0000000 module modreq_obj_global 1.0; require { class file { read }; } type mod_global_t; type mod_foo_t; type mod_bar_t; optional { require { class sem { create destroy }; } type mod_opt_t; allow mod_foo_t mod_bar_t : sem { create destroy }; } libsepol/tests/policies/test-deps/modreq-perm-global.conf0100644 0000000 0000000 00000000227 13756670065 022654 0ustar000000000 0000000 module modreq_perm_global 1.0; require { class msg { send receive }; } type mod_global_t; type a_t; type b_t; allow a_t b_t: msg { send receive }; libsepol/tests/policies/test-deps/modreq-perm-opt.conf0100644 0000000 0000000 00000000362 13756670065 022216 0ustar000000000 0000000 module modreq_perm_opt 1.0; require { class file { read write }; } type mod_global_t; optional { require { class msg { send receive }; } type mod_opt_t; type a_mod_t; type b_mod_t; allow a_mod_t b_mod_t: msg { send receive }; } libsepol/tests/policies/test-deps/modreq-role-global.conf0100644 0000000 0000000 00000000236 13756670065 022652 0ustar000000000 0000000 module modreq_role_global 1.0; require { role role_req_r, user_r; } type mod_global_t; type a_t; # role role_req_r types a_t; allow role_req_r user_r; libsepol/tests/policies/test-deps/modreq-role-opt.conf0100644 0000000 0000000 00000000275 13756670065 022217 0ustar000000000 0000000 module modreq_role_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { role role_req_r, user_r; } type mod_opt_t; allow role_req_r user_r; } libsepol/tests/policies/test-deps/modreq-type-global.conf0100644 0000000 0000000 00000000255 13756670065 022673 0ustar000000000 0000000 module modreq_type_global 1.0; require { type type_req_t; class file { read write }; } type mod_global_t; type test_t; allow test_t type_req_t : file { read write }; libsepol/tests/policies/test-deps/modreq-type-opt.conf0100644 0000000 0000000 00000000327 13756670065 022235 0ustar000000000 0000000 module modreq_type_opt 1.0; require { type file_t; class file { read write }; } type mod_global_t; optional { require { type type_req_t; } type mod_opt_t; allow type_req_t file_t : file { read write }; }libsepol/tests/policies/test-deps/module.conf0100644 0000000 0000000 00000000472 13756670065 020455 0ustar000000000 0000000 module my_module 1.0; require { bool secure_mode; type system_t, sysadm_t, file_t; attribute domain; role system_r; class file {read write}; } type new_t, domain; role system_r types new_t; allow system_t file_t : file { read write }; if (secure_mode) { allow sysadm_t file_t : file { read write }; } libsepol/tests/policies/test-deps/small-base.conf0100644 0000000 0000000 00000016155 13756670065 021215 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r types sys_foo_t; type user_t, domain; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:net_foo_t, s0) libsepol/tests/policies/test-expander/0040755 0000000 0000000 00000000000 13756670065 017174 5ustar000000000 0000000 libsepol/tests/policies/test-expander/alias-base.conf0100644 0000000 0000000 00000015421 13756670065 022044 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') type enable_optional; # Alias tests type alias_check_1_t; type alias_check_2_t; type alias_check_3_t; typealias alias_check_1_t alias alias_check_1_a; optional { require { type alias_check_2_t; } typealias alias_check_2_t alias alias_check_2_a; } optional { require { type alias_check_3_a; } allow alias_check_3_a enable_optional:file read; } ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:system_t, s0) libsepol/tests/policies/test-expander/alias-module.conf0100644 0000000 0000000 00000000156 13756670065 022416 0ustar000000000 0000000 module my_module 1.0; require { type alias_check_3_t; } typealias alias_check_3_t alias alias_check_3_a; libsepol/tests/policies/test-expander/base-base-only.conf0100644 0000000 0000000 00000000723 13756670065 022643 0ustar000000000 0000000 class security class file sid kernel common file { read } class file inherits file { entrypoint } class security { compute_av } ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; level s0:c0; mlsconstrain file { read } ( h1 dom h2 ); ') attribute myattr; type mytype_t; role myrole_r; role myrole_r types mytype_t; bool mybool true; gen_user(myuser_u,, myrole_r, s0, s0 - s0:c0) sid kernel gen_context(myuser_u:myrole_r:mytype_t, s0) libsepol/tests/policies/test-expander/module.conf0100644 0000000 0000000 00000014067 13756670065 021335 0ustar000000000 0000000 module my_module 1.0; require { bool allow_ypbind, secure_mode, allow_execstack; type system_t, sysadm_t; class file {read write}; attribute attr_check_base_2, attr_check_base_3; attribute attr_check_base_optional_2; } bool module_1_bool true; if (module_1_bool && allow_ypbind && secure_mode && allow_execstack) { allow system_t sysadm_t : file { read write }; } optional { bool module_1_bool_2 false; require { bool optional_bool_1, optional_bool_2; class file { execute ioctl }; } if (optional_bool_1 && optional_bool_2 || module_1_bool_2) { allow system_t sysadm_t : file {execute ioctl}; } } # Type - attribute mapping test type module_t; attribute attr_check_mod_1; attribute attr_check_mod_2; attribute attr_check_mod_3; attribute attr_check_mod_4; attribute attr_check_mod_5; attribute attr_check_mod_6; attribute attr_check_mod_7; attribute attr_check_mod_8; attribute attr_check_mod_9; attribute attr_check_mod_10; attribute attr_check_mod_11; optional { require { type base_t; } attribute attr_check_mod_optional_1; attribute attr_check_mod_optional_2; attribute attr_check_mod_optional_3; attribute attr_check_mod_optional_4; attribute attr_check_mod_optional_5; attribute attr_check_mod_optional_6; attribute attr_check_mod_optional_7; } optional { require { type does_not_exist_t; } attribute attr_check_mod_optional_disabled_4; attribute attr_check_mod_optional_disabled_7; } type attr_check_base_2_1_t, attr_check_base_2; type attr_check_base_2_2_t; typeattribute attr_check_base_2_2_t attr_check_base_2; type attr_check_base_3_3_t, attr_check_base_3; type attr_check_base_3_4_t; typeattribute attr_check_base_3_4_t attr_check_base_3; optional { require { attribute attr_check_base_5; } type attr_check_base_5_1_t, attr_check_base_5; type attr_check_base_5_2_t; typeattribute attr_check_base_5_2_t attr_check_base_5; } optional { require { attribute attr_check_base_6; } type attr_check_base_6_3_t, attr_check_base_6; type attr_check_base_6_4_t; typeattribute attr_check_base_6_4_t attr_check_base_6; } optional { require { type does_not_exist_t; attribute attr_check_base_8; } type attr_check_base_8_1_t, attr_check_base_8; type attr_check_base_8_2_t; typeattribute attr_check_base_8_2_t attr_check_base_8; } optional { require { type does_not_exist_t; attribute attr_check_base_9; } type attr_check_base_9_3_t, attr_check_base_9; type attr_check_base_9_4_t; typeattribute attr_check_base_9_4_t attr_check_base_9; } optional { require { type does_not_exist_t; attribute attr_check_base_10; } type attr_check_base_10_3_t, attr_check_base_10; type attr_check_base_10_4_t; typeattribute attr_check_base_10_4_t attr_check_base_10; } optional { require { attribute attr_check_base_11; } type attr_check_base_11_3_t, attr_check_base_11; type attr_check_base_11_4_t; typeattribute attr_check_base_11_4_t attr_check_base_11; } type attr_check_base_optional_2_1_t, attr_check_base_optional_2; type attr_check_base_optional_2_2_t; typeattribute attr_check_base_optional_2_2_t attr_check_base_optional_2; optional { require { attribute attr_check_base_optional_5; } type attr_check_base_optional_5_1_t, attr_check_base_optional_5; type attr_check_base_optional_5_2_t; typeattribute attr_check_base_optional_5_2_t attr_check_base_optional_5; } #optional { # require { # attribute attr_check_base_optional_6; # } # type attr_check_base_optional_6_3_t, attr_check_base_optional_6; # type attr_check_base_optional_6_4_t; # typeattribute attr_check_base_optional_6_4_t attr_check_base_optional_6; #} optional { require { type does_not_exist_t; attribute attr_check_base_optional_8; } type attr_check_base_optional_8_1_t, attr_check_base_optional_8; type attr_check_base_optional_8_2_t; typeattribute attr_check_base_optional_8_2_t attr_check_base_optional_8; } type attr_check_mod_2_1_t, attr_check_mod_2; type attr_check_mod_2_2_t; typeattribute attr_check_mod_2_2_t attr_check_mod_2; optional { require { attribute attr_check_mod_5; } type attr_check_mod_5_1_t, attr_check_mod_5; type attr_check_mod_5_2_t; typeattribute attr_check_mod_5_2_t attr_check_mod_5; } optional { require { attribute attr_check_mod_6; } type attr_check_mod_6_3_t, attr_check_mod_6; type attr_check_mod_6_4_t; typeattribute attr_check_mod_6_4_t attr_check_mod_6; } optional { require { type does_not_exist_t; } type attr_check_mod_8_1_t, attr_check_mod_8; type attr_check_mod_8_2_t; typeattribute attr_check_mod_8_2_t attr_check_mod_8; } optional { require { type does_not_exist_t; } type attr_check_mod_9_3_t, attr_check_mod_9; type attr_check_mod_9_4_t; typeattribute attr_check_mod_9_4_t attr_check_mod_9; } optional { require { type does_not_exist_t; } type attr_check_mod_10_3_t, attr_check_mod_10; type attr_check_mod_10_4_t; typeattribute attr_check_mod_10_4_t attr_check_mod_10; } optional { require { type base_t; } type attr_check_mod_11_3_t, attr_check_mod_11; type attr_check_mod_11_4_t; typeattribute attr_check_mod_11_4_t attr_check_mod_11; } #optional { # require { # attribute attr_check_mod_optional_5; # } # type attr_check_mod_optional_5_1_t, attr_check_mod_optional_5; # type attr_check_mod_optional_5_2_t; # typeattribute attr_check_mod_optional_5_2_t attr_check_mod_optional_5; #} #optional { # require { # attribute attr_check_mod_optional_6; # } # type attr_check_mod_optional_6_3_t, attr_check_mod_optional_6; # type attr_check_mod_optional_6_4_t; # typeattribute attr_check_mod_optional_6_4_t attr_check_mod_optional_6; #} optional { require { attribute attr_check_base_optional_disabled_5; } type attr_check_base_optional_disabled_5_1_t, attr_check_base_optional_disabled_5; type attr_check_base_optional_disabled_5_2_t; typeattribute attr_check_base_optional_disabled_5_2_t attr_check_base_optional_disabled_5; } optional { require { type does_not_exist_t; attribute attr_check_base_optional_disabled_8; } type attr_check_base_optional_disabled_8_1_t, attr_check_base_optional_disabled_8; type attr_check_base_optional_disabled_8_2_t; typeattribute attr_check_base_optional_disabled_8_2_t attr_check_base_optional_disabled_8; } libsepol/tests/policies/test-expander/role-base.conf0100644 0000000 0000000 00000015024 13756670065 021713 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') # Role mapping test type role_check_1_1_t; role role_check_1; role role_check_1 types role_check_1_1_t; ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:system_t, s0) libsepol/tests/policies/test-expander/role-module.conf0100644 0000000 0000000 00000000224 13756670065 022262 0ustar000000000 0000000 module my_module 1.0; require { class file {read write}; role role_check_1; } type role_check_1_2_t; role role_check_1 types role_check_1_2_t; libsepol/tests/policies/test-expander/small-base.conf0100644 0000000 0000000 00000031365 13756670065 022070 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; # Type - attribute mapping test # Shorthand tests # 1 = types in base, 2 = types in mod, 3 = types in both # 4 = types in optional in base, 5 = types in optional in mod # 6 = types in optional in both # 7 = types in disabled optional in base # 8 = types in disabled optional in module # 9 = types in disabled optional in both # 10 = types in enabled optional in base, disabled optional in module # 11 = types in disabled optional in base, enabled optional in module attribute attr_check_base_1; attribute attr_check_base_2; attribute attr_check_base_3; attribute attr_check_base_4; attribute attr_check_base_5; attribute attr_check_base_6; attribute attr_check_base_7; attribute attr_check_base_8; attribute attr_check_base_9; attribute attr_check_base_10; attribute attr_check_base_11; optional { require { type module_t; } attribute attr_check_base_optional_1; attribute attr_check_base_optional_2; attribute attr_check_base_optional_3; attribute attr_check_base_optional_4; attribute attr_check_base_optional_5; attribute attr_check_base_optional_6; attribute attr_check_base_optional_8; } optional { require { type does_not_exist_t; } attribute attr_check_base_optional_disabled_5; attribute attr_check_base_optional_disabled_8; } type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } # Type - attribute mapping test type base_t; type attr_check_base_1_1_t, attr_check_base_1; type attr_check_base_1_2_t; typeattribute attr_check_base_1_2_t attr_check_base_1; type attr_check_base_3_1_t, attr_check_base_3; type attr_check_base_3_2_t; typeattribute attr_check_base_3_2_t attr_check_base_3; optional { require { attribute attr_check_base_4; } type attr_check_base_4_1_t, attr_check_base_4; type attr_check_base_4_2_t; typeattribute attr_check_base_4_2_t attr_check_base_4; } optional { require { type module_t; } type attr_check_base_6_1_t, attr_check_base_6; type attr_check_base_6_2_t; typeattribute attr_check_base_6_2_t attr_check_base_6; } optional { require { type does_not_exist_t; } type attr_check_base_7_1_t, attr_check_base_7; type attr_check_base_7_2_t; typeattribute attr_check_base_7_2_t attr_check_base_7; } optional { require { type does_not_exist_t; } type attr_check_base_9_1_t, attr_check_base_9; type attr_check_base_9_2_t; typeattribute attr_check_base_9_2_t attr_check_base_9; } optional { require { type module_t; } type attr_check_base_10_1_t, attr_check_base_10; type attr_check_base_10_2_t; typeattribute attr_check_base_10_2_t attr_check_base_10; } optional { require { type does_not_exist_t; } type attr_check_base_11_1_t, attr_check_base_11; type attr_check_base_11_2_t; typeattribute attr_check_base_11_2_t attr_check_base_11; } #optional { # require { # attribute attr_check_base_optional_4; # } # type attr_check_base_optional_4_1_t, attr_check_base_optional_4; # type attr_check_base_optional_4_2_t; # typeattribute attr_check_base_optional_4_2_t attr_check_base_optional_4; #} #optional { # require { # attribute attr_check_base_optional_6; # } # type attr_check_base_optional_6_1_t, attr_check_base_optional_6; # type attr_check_base_optional_6_2_t; # typeattribute attr_check_base_optional_6_2_t attr_check_base_optional_6; #} optional { require { attribute attr_check_mod_4; } type attr_check_mod_4_1_t, attr_check_mod_4; type attr_check_mod_4_2_t; typeattribute attr_check_mod_4_2_t attr_check_mod_4; } optional { require { attribute attr_check_mod_6; } type attr_check_mod_6_1_t, attr_check_mod_6; type attr_check_mod_6_2_t; typeattribute attr_check_mod_6_2_t attr_check_mod_6; } optional { require { type does_not_exist_t; attribute attr_check_mod_7; } type attr_check_mod_7_1_t, attr_check_mod_7; type attr_check_mod_7_2_t; typeattribute attr_check_mod_7_2_t attr_check_mod_7; } optional { require { type does_not_exist_t; attribute attr_check_mod_9; } type attr_check_mod_9_1_t, attr_check_mod_9; type attr_check_mod_9_2_t; typeattribute attr_check_mod_9_2_t attr_check_mod_9; } optional { require { attribute attr_check_mod_10; } type attr_check_mod_10_1_t, attr_check_mod_10; type attr_check_mod_10_2_t; typeattribute attr_check_mod_10_2_t attr_check_mod_10; } optional { require { type does_not_exist_t; attribute attr_check_mod_11; } type attr_check_mod_11_1_t, attr_check_mod_11; type attr_check_mod_11_2_t; typeattribute attr_check_mod_11_2_t attr_check_mod_11; } optional { require { attribute attr_check_mod_optional_4; } type attr_check_mod_optional_4_1_t, attr_check_mod_optional_4; type attr_check_mod_optional_4_2_t; typeattribute attr_check_mod_optional_4_2_t attr_check_mod_optional_4; } optional { require { attribute attr_check_mod_optional_6; } type attr_check_mod_optional_6_1_t, attr_check_mod_optional_6; type attr_check_mod_optional_6_2_t; typeattribute attr_check_mod_optional_6_2_t attr_check_mod_optional_6; } optional { require { type does_not_exist_t; attribute attr_check_mod_optional_7; } type attr_check_mod_optional_7_1_t, attr_check_mod_optional_7; type attr_check_mod_optional_7_2_t; typeattribute attr_check_mod_optional_7_2_t attr_check_mod_optional_7; } optional { require { attribute attr_check_mod_optional_disabled_4; } type attr_check_mod_optional_disabled_4_1_t, attr_check_mod_optional_disabled_4; type attr_check_mod_optional_disabled_4_2_t; typeattribute attr_check_mod_optional_disabled_4_2_t attr_check_mod_optional_disabled_4; } optional { require { type does_not_exist_t; attribute attr_check_mod_optional_disabled_7; } type attr_check_mod_optional_disabled_7_1_t, attr_check_mod_optional_disabled_7; type attr_check_mod_optional_disabled_7_2_t; typeattribute attr_check_mod_optional_disabled_7_2_t attr_check_mod_optional_disabled_7; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:net_foo_t, s0) libsepol/tests/policies/test-expander/user-base.conf0100644 0000000 0000000 00000015307 13756670065 021734 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') # User mapping test type user_check_1_1_t; type user_check_1_2_t; role user_check_1_1_r; role user_check_1_2_r; role user_check_1_1_r types user_check_1_1_t; role user_check_1_2_r types user_check_1_2_t; ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(user_check_1,, user_check_1_1_r user_check_1_2_r, s0, s0 - s0:c0.c23) gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(system_u:object_r:system_t, s0) libsepol/tests/policies/test-expander/user-module.conf0100644 0000000 0000000 00000000153 13756670065 022300 0ustar000000000 0000000 module my_module 1.0; require { class file {read write}; ifdef(`enable_mls',` user user_check_1; ') } libsepol/tests/policies/test-hooks/0040755 0000000 0000000 00000000000 13756670065 016511 5ustar000000000 0000000 libsepol/tests/policies/test-hooks/cmp_policy.conf0100644 0000000 0000000 00000014403 13756670065 021515 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type g_b_type_1; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_1; role g_b_role_3 types g_b_type_1; type g_b_type_2; optional { require { type invalid_type; } allow g_b_role_2 g_b_role_3; role_transition g_b_role_2 g_b_type_2 g_b_role_3; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol/tests/policies/test-hooks/module_add_role_allow_trans.conf0100644 0000000 0000000 00000000325 13756670065 025100 0ustar000000000 0000000 module add_symbol_test 1.0; require { class file { read }; } role role_a_1; role role_a_2; role role_t_1; role role_t_2; type type_rt_1; allow role_a_1 role_a_2; role_transition role_t_1 type_rt_1 role_t_2; libsepol/tests/policies/test-hooks/module_add_symbols.conf0100644 0000000 0000000 00000000330 13756670065 023216 0ustar000000000 0000000 module add_symbol_test 1.0; require { class file { read write }; } type type_add_1; attribute attrib_add_1; role role_add_1; bool bool_add_1 false; ifdef(`enable_mls',`',` user user_add_1 roles { role_add_1 }; ') libsepol/tests/policies/test-hooks/small-base.conf0100644 0000000 0000000 00000014403 13756670065 021377 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type g_b_type_1; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_1; role g_b_role_3 types g_b_type_1; type g_b_type_2; optional { require { type invalid_type; } allow g_b_role_2 g_b_role_3; role_transition g_b_role_2 g_b_type_2 g_b_role_3; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol/tests/policies/test-linker/0040755 0000000 0000000 00000000000 13756670065 016652 5ustar000000000 0000000 libsepol/tests/policies/test-linker/module1.conf0100644 0000000 0000000 00000005575 13756670065 021100 0ustar000000000 0000000 module linker_test_1 1.0; require { class file { read write }; class lnk_file append; role g_b_role_2; attribute g_b_attr_3; attribute g_b_attr_5; attribute o4_b_attr_1; type g_b_type_3; } type tag_g_m1; #test for type in module and attr in module, added to in module attribute g_m1_attr_1; type g_m1_type_1, g_m1_attr_1; type g_m1_type_2; typeattribute g_m1_type_2 g_m1_attr_1; #add role in module test role g_m1_role_1; role g_m1_role_1 types g_m1_type_1; # test for attr declared in base, added to in module type g_m1_type_3; typeattribute g_m1_type_3 g_b_attr_3; # test for attr declared in base, added to in 2 modules type g_m1_type_4; typeattribute g_m1_type_4 g_b_attr_5; # test for attr declared in base optional, added to in module type g_m1_type_5; typeattribute g_m1_type_5 o4_b_attr_1; # test for attr declared in module, added to in base optional attribute g_m1_attr_2; #add type to base role test role g_b_role_2 types g_m1_type_1; role g_b_role_3; role g_b_role_3 types g_m1_type_2; #add type to base optional role test role o1_b_role_2; role o1_b_role_2 types g_m1_type_1; #optional base role w/ adds in 2 modules role o4_b_role_1; role o4_b_role_1 types g_m1_type_2; # attr a added to in base optional, declared/added to in module, added to in other module attribute g_m1_attr_3; type g_m1_type_6, g_m1_attr_3; # attr a added to in base optional, declared/added in module , added to in other module optional attribute g_m1_attr_4; type g_m1_type_7, g_m1_attr_4; # alias tests typealias g_b_type_3 alias g_m_alias_1; # single boolean in module bool g_m1_bool_1 true; if (g_m1_bool_1) { allow g_m1_type_1 g_m1_type_2 : lnk_file append; } optional { require { type optional_type; attribute g_b_attr_4; attribute o1_b_attr_2; class lnk_file { ioctl }; } type tag_o1_m1; attribute o1_m1_attr_1; type o1_m1_type_2, o1_m1_attr_1; type o1_m1_type_1; role o1_m1_role_1; role o1_m1_role_1 types o1_m1_type_1; type o1_m1_type_3; typeattribute o1_m1_type_3 g_b_attr_4; type o1_m1_type_5; typeattribute o1_m1_type_5 o1_b_attr_2; bool o1_m1_bool_1 false; if (o1_m1_bool_1) { allow o1_m1_type_2 o1_m1_type_1 : lnk_file ioctl; } } optional { require { type optional_type; #role g_b_role_4; // This causes a bug where the role scope doesn't get copied into base } type tag_o2_m1; role g_b_role_4; role g_b_role_4 types g_m1_type_2; } optional { require { attribute g_b_attr_6; } type tag_o3_m1; type o3_m1_type_1; role o3_b_role_1; role o3_b_role_1 types o3_m1_type_1; type o3_m1_type_2, g_b_attr_6; attribute o3_m1_attr_1; # attr a added to in base optional, declared/added in module optional, added to in other module attribute o3_m1_attr_2; type o3_m1_type_3, o3_m1_attr_2; } optional { require { type enable_optional; } type tag_o4_m1; attribute o4_m1_attr_1; type o4_m1_type_1; typeattribute o4_m1_type_1 o4_m1_attr_1; } libsepol/tests/policies/test-linker/module2.conf0100644 0000000 0000000 00000002365 13756670065 021073 0ustar000000000 0000000 module linker_test_2 1.0; require { class file { read write }; class lnk_file { unlink }; attribute g_b_attr_5; attribute g_b_attr_6; attribute g_m1_attr_3; attribute o3_m1_attr_2; } type tag_g_m2; type g_m2_type_1; role g_m2_role_1; role g_m2_role_1 types g_m2_type_1; type g_m2_type_4, g_b_attr_5; type g_m2_type_5, g_b_attr_6; #add types to role declared in base test type g_m2_type_2; role g_b_role_3; role g_b_role_3 types g_m2_type_2; #optional base role w/ adds in 2 modules role o4_b_role_1; role o4_b_role_1 types g_m2_type_1; # attr a added to in base optional, declared/added to in module, added to in other module type g_m2_type_3, g_m1_attr_3; # attr a added to in base optional, declared/added in module optional, added to in other module type g_m2_type_6, o3_m1_attr_2; # cond mapping tests bool g_m2_bool_1 true; bool g_m2_bool_2 false; if (g_m2_bool_1 && g_m2_bool_2) { allow g_m2_type_1 g_m2_type_2 : lnk_file unlink; } optional { require { type optional_type; } type tag_o1_m2; type o1_m2_type_1; role o1_m2_role_1; role o1_m2_role_1 types o1_m2_type_1; } optional { require { attribute g_m1_attr_4; attribute o4_m1_attr_1; } type tag_o2_m2; type o2_m2_type_1, g_m1_attr_4; type o2_m2_type_2, o4_m1_attr_1; } libsepol/tests/policies/test-linker/small-base.conf0100644 0000000 0000000 00000020766 13756670065 021551 0ustar000000000 0000000 # FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related clases class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controling capabilies # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type enable_optional; #decorative type for finding this decl, every block should have one type tag_g_b; attribute g_b_attr_1; attribute g_b_attr_2; attribute g_b_attr_3; attribute g_b_attr_4; attribute g_b_attr_5; attribute g_b_attr_6; type g_b_type_1, g_b_attr_1; type g_b_type_2, g_b_attr_2; type g_b_type_3; role g_b_role_1; role g_b_role_2; role g_b_role_3; role g_b_role_4; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_2; role g_b_role_3 types g_b_type_2; role g_b_role_4 types g_b_type_2; bool g_b_bool_1 false; bool g_b_bool_2 true; allow g_b_type_1 g_b_type_2 : security { compute_av load_policy }; allow g_b_type_1 g_b_type_2 : file *; # test * allow g_b_type_1 g_b_type_2 : process ~ptrace; #test ~ typealias g_b_type_3 alias g_b_alias_1; if (g_b_bool_1) { allow g_b_type_1 g_b_type_2: lnk_file read; } optional { require { type enable_optional; attribute g_m1_attr_2; } type tag_o1_b; attribute o1_b_attr_1; type o1_b_type_1, o1_b_attr_1; bool o1_b_bool_1 true; role o1_b_role_1; role o1_b_role_1 types o1_b_type_1; role o1_b_role_2; role o1_b_role_2 types o1_b_type_1; attribute o1_b_attr_2; type o1_b_type_2, g_m1_attr_2; if (o1_b_bool_1) { allow o1_b_type_1 o1_b_type_2: lnk_file write; } } optional { require { # this should be activated by module 1 type g_m1_type_1; attribute o3_m1_attr_2; } type tag_o2_b; type o2_b_type_1, o3_m1_attr_2; } optional { require { #this block should not come on type invalid_type; } type tag_o3_b; attribute o3_b_attr_1; type o3_b_type_1; bool o3_b_bool_1 true; role o3_b_role_1; role o3_b_role_1 types o3_b_type_1; allow g_b_type_1 invalid_type : sem { create destroy }; } optional { require { # also should be enabled by module 1 type enable_optional; type g_m1_type_1; attribute o3_m1_attr_1; attribute g_m1_attr_3; } type tag_o4_b; attribute o4_b_attr_1; role o4_b_role_1; role o4_b_role_1 types g_m1_type_1; # test for attr declared in module optional, added to in base optional type o4_b_type_1, o3_m1_attr_1; type o4_b_type_2, g_m1_attr_3; } optional { require { attribute g_m1_attr_4; attribute o4_m1_attr_1; } type tag_o5_b; type o5_b_type_1, g_m1_attr_4; type o5_b_type_2, o4_m1_attr_1; } optional { require { type enable_optional; } type tag_o6_b; typealias g_b_type_3 alias g_b_alias_2; } optional { require { type g_m_alias_1; } type tag_o7_b; allow g_m_alias_1 enable_optional:file read; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) gen_user(g_b_user_2,, g_b_role_1, s0, s0 - s0:c0, c1, c3, c4, c5) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:: gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol/tests/test-common.c0100644 0000000 0000000 00000017003 13756670065 015211 0ustar000000000 0000000 /* * Author: Joshua Brindle * Chad Sellers * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This has tests that are common between test suites*/ #include #include void test_sym_presence(policydb_t * p, const char *id, int sym_type, unsigned int scope_type, unsigned int *decls, unsigned int len) { scope_datum_t *scope; int found; unsigned int i, j; /* make sure it is in global symtab */ if (!hashtab_search(p->symtab[sym_type].table, id)) { fprintf(stderr, "symbol %s not found in table %d\n", id, sym_type); CU_FAIL_FATAL(); } /* make sure its scope is correct */ scope = hashtab_search(p->scope[sym_type].table, id); CU_ASSERT_FATAL(scope != NULL); CU_ASSERT(scope->scope == scope_type); CU_ASSERT(scope->decl_ids_len == len); if (scope->decl_ids_len != len) fprintf(stderr, "sym %s has %d decls, %d expected\n", id, scope->decl_ids_len, len); for (i = 0; i < len; i++) { found = 0; for (j = 0; j < len; j++) { if (decls[i] == scope->decl_ids[j]) found++; } CU_ASSERT(found == 1); } } static int common_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { common_datum_t *d = (common_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_COMMONS][d->s.value - 1] == (char *)key); return 0; } static int class_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { class_datum_t *d = (class_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_CLASSES][d->s.value - 1] == (char *)key); CU_ASSERT(p->class_val_to_struct[d->s.value - 1] == d); return 0; } static int role_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { role_datum_t *d = (role_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_ROLES][d->s.value - 1] == (char *)key); CU_ASSERT(p->role_val_to_struct[d->s.value - 1] == d); return 0; } static int type_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { type_datum_t *d = (type_datum_t *) datum; policydb_t *p = (policydb_t *) data; if (!d->primary) return 0; CU_ASSERT(p->sym_val_to_name[SYM_TYPES][d->s.value - 1] == (char *)key); CU_ASSERT(p->type_val_to_struct[d->s.value - 1] == d); return 0; } static int user_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { user_datum_t *d = (user_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_USERS][d->s.value - 1] == (char *)key); CU_ASSERT(p->user_val_to_struct[d->s.value - 1] == d); return 0; } static int cond_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { cond_bool_datum_t *d = (cond_bool_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_BOOLS][d->s.value - 1] == (char *)key); CU_ASSERT(p->bool_val_to_struct[d->s.value - 1] == d); return 0; } static int level_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { level_datum_t *d = (level_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_LEVELS][d->level->sens - 1] == (char *)key); return 0; } static int cat_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { cat_datum_t *d = (cat_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_CATS][d->s.value - 1] == (char *)key); return 0; } static int (*test_index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *p) = { common_test_index, class_test_index, role_test_index, type_test_index, user_test_index, cond_test_index, level_test_index, cat_test_index,}; void test_policydb_indexes(policydb_t * p) { int i; for (i = 0; i < SYM_NUM; i++) { hashtab_map(p->symtab[i].table, test_index_f[i], p); } } void test_alias_datum(policydb_t * p, const char *id, const char *primary_id, char mode, unsigned int flavor) { type_datum_t *type, *primary; unsigned int my_primary, my_flavor, my_value; type = hashtab_search(p->p_types.table, id); primary = hashtab_search(p->p_types.table, primary_id); CU_ASSERT_PTR_NOT_NULL(type); CU_ASSERT_PTR_NOT_NULL(primary); if (type && primary) { if (mode) { my_flavor = type->flavor; } else { my_flavor = flavor; } if (my_flavor == TYPE_TYPE) { my_primary = 0; my_value = primary->s.value; } else { CU_ASSERT(my_flavor == TYPE_ALIAS); my_primary = primary->s.value; CU_ASSERT_NOT_EQUAL(type->s.value, primary->s.value); my_value = type->s.value; } CU_ASSERT(type->primary == my_primary); CU_ASSERT(type->flavor == my_flavor); CU_ASSERT(type->s.value == my_value); } } role_datum_t *test_role_type_set(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, unsigned int len, unsigned int flags) { ebitmap_node_t *tnode; unsigned int i, j, new, found = 0; role_datum_t *role; if (decl) role = hashtab_search(decl->p_roles.table, id); else role = hashtab_search(p->p_roles.table, id); if (!role) printf("role %s can't be found! \n", id); CU_ASSERT_FATAL(role != NULL); ebitmap_for_each_bit(&role->types.types, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { new = 0; for (j = 0; j < len; j++) { if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) { found++; new = 1; } } if (new == 0) { printf("\nRole %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]); } CU_ASSERT(new == 1); } } CU_ASSERT(found == len); if (found != len) printf("\nrole %s has %d types, %d expected\n", p->sym_val_to_name[SYM_ROLES][role->s.value - 1], found, len); /* roles should never have anything in the negset */ CU_ASSERT(role->types.negset.highbit == 0); CU_ASSERT(role->types.flags == flags); return role; } void test_attr_types(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, int len) { ebitmap_node_t *tnode; int j, new, found = 0; unsigned int i; type_datum_t *attr; if (decl) attr = hashtab_search(decl->p_types.table, id); else attr = hashtab_search(p->p_types.table, id); if (attr == NULL) printf("could not find attr %s in decl %d\n", id, decl->decl_id); CU_ASSERT_FATAL(attr != NULL); CU_ASSERT(attr->flavor == TYPE_ATTRIB); CU_ASSERT(attr->primary == 1); ebitmap_for_each_bit(&attr->types, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { new = 0; for (j = 0; j < len; j++) { if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) { found++; new = 1; } } if (new == 0) { printf("\nattr %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]); } CU_ASSERT(new == 1); } } CU_ASSERT(found == len); if (found != len) printf("\nattr %s has %d types, %d expected\n", id, found, len); } libsepol/tests/test-common.h0100644 0000000 0000000 00000006664 13756670065 015231 0ustar000000000 0000000 /* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_COMMON_H__ #define __TEST_COMMON_H__ #include /* p the policy being inspected * id string symbol identifier * sym_type symbol type (eg., SYM_ROLES, SYM_TYPES) * scope_type what scope the role should have (eg., SCOPE_DECL or SCOPE_REQ) * decls integer array of decl id's that we expect the role to have in the scope table * len number of elements in decls * * This is a utility function to test for the symbol's presence in the global symbol table, * the scope table, and that the decl blocks we think this symbol is in are correct */ extern void test_sym_presence(policydb_t * p, const char *id, int sym_type, unsigned int scope_type, unsigned int *decls, unsigned int len); /* Test the indexes in the policydb to ensure their correctness. These include * the sym_val_to_name[], class_val_to_struct, role_val_to_struct, type_val_to_struct, * user_val_to_struct, and bool_val_to_struct indexes. */ extern void test_policydb_indexes(policydb_t * p); /* Test alias datum to ensure that it is as expected * * id = the key for the alias * primary_id = the key for its primary * mode: 0 = test the datum according to the flavor value in the call 1 = automatically detect the flavor value and test the datum accordingly * flavor = flavor value if in mode 0 */ extern void test_alias_datum(policydb_t * p, const char *id, const char *primary_id, char mode, unsigned int flavor); /* p the policy being inspected * id string role identifier * decl the decl block which we are looking in for the role datum * types the array of string types which we expect the role has in its type ebitmap * len number of elements in types * flags the expected flags in the role typeset (eg., * or ~) * * This is a utility function to test whether the type set associated with a role in a specific * avrule decl block matches our expectations */ extern role_datum_t *test_role_type_set(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, unsigned int len, unsigned int flags); /* p the policy being inspected * id string attribute identifier * decl the decl block which we are looking in for the attribute datum * types the array of string types which we expect the attribute has in its type ebitmap * len number of elements in types * * This is a utility function to test whether the type set associated with an attribute in a specific * avrule decl block matches our expectations */ extern void test_attr_types(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, int len); #endif libsepol/tests/test-cond.c0100644 0000000 0000000 00000004375 13756670065 014654 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-cond.h" #include "parse_util.h" #include "helpers.h" #include #include #include #include static policydb_t basemod; static policydb_t base_expanded; int cond_test_init(void) { if (policydb_init(&base_expanded)) { fprintf(stderr, "out of memory!\n"); policydb_destroy(&basemod); return -1; } if (test_load_policy(&basemod, POLICY_BASE, 1, "test-cond", "refpolicy-base.conf")) goto cleanup; if (link_modules(NULL, &basemod, NULL, 0, 0)) { fprintf(stderr, "link modules failed\n"); goto cleanup; } if (expand_module(NULL, &basemod, &base_expanded, 0, 1)) { fprintf(stderr, "expand module failed\n"); goto cleanup; } return 0; cleanup: policydb_destroy(&basemod); policydb_destroy(&base_expanded); return -1; } int cond_test_cleanup(void) { policydb_destroy(&basemod); policydb_destroy(&base_expanded); return 0; } static void test_cond_expr_equal(void) { cond_node_t *a, *b; a = base_expanded.cond_list; while (a) { b = base_expanded.cond_list; while (b) { if (a == b) { CU_ASSERT(cond_expr_equal(a, b)); } else { CU_ASSERT(cond_expr_equal(a, b) == 0); } b = b->next; } a = a->next; } } int cond_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "cond_expr_equal", test_cond_expr_equal)) { return CU_get_error(); } return 0; } libsepol/tests/test-cond.h0100644 0000000 0000000 00000002010 13756670065 014641 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_COND_H__ #define __TEST_COND_H__ #include int cond_test_init(void); int cond_test_cleanup(void); int cond_add_tests(CU_pSuite suite); #endif libsepol/tests/test-deps.c0100644 0000000 0000000 00000024050 13756670065 014654 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-deps.h" #include "parse_util.h" #include "helpers.h" #include #include #include /* Tests for dependency checking / handling, specifically: * * 1 type in module global. * 2 attribute in module global. * 3 object class / perm in module global. * 4 boolean in module global. * 5 role in module global. * * 6 type in module optional. * 7 attribute in module optional. * 8 object class / perm in module optional. * 9 boolean in module optional. * 10 role in module optional. * * 11 type in base optional. * 12 attribute in base optional. * 13 object class / perm in base optional. * 14 boolean in base optional. * 15 role in base optional. * * Each of these tests are done with the dependency met and not * met. Additionally, each of the required symbols is used in the * scope it is required. * * In addition to the simple tests, we have test with more complex * modules that test: * * 17 mutual dependencies between two modules. * 18 circular dependency between three modules. * 19 large number of dependencies in a module with a more complex base. * 20 nested optionals with requires. * * Again, each of these tests is done with the requirements met and not * met. */ #include #include #define BASE_MODREQ_TYPE_GLOBAL 0 #define BASE_MODREQ_ATTR_GLOBAL 1 #define BASE_MODREQ_OBJ_GLOBAL 2 #define BASE_MODREQ_BOOL_GLOBAL 3 #define BASE_MODREQ_ROLE_GLOBAL 4 #define BASE_MODREQ_PERM_GLOBAL 5 #define BASE_MODREQ_TYPE_OPT 6 #define BASE_MODREQ_ATTR_OPT 7 #define BASE_MODREQ_OBJ_OPT 8 #define BASE_MODREQ_BOOL_OPT 9 #define BASE_MODREQ_ROLE_OPT 10 #define BASE_MODREQ_PERM_OPT 11 #define NUM_BASES 12 static policydb_t bases_met[NUM_BASES]; static policydb_t bases_notmet[NUM_BASES]; extern int mls; int deps_test_init(void) { int i; /* To test linking we need 1 base per link test and in * order to load them in the init function we have * to keep them all around. Not ideal, but it shouldn't * matter too much. */ for (i = 0; i < NUM_BASES; i++) { if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) return -1; } for (i = 0; i < NUM_BASES; i++) { if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) return -1; } return 0; } int deps_test_cleanup(void) { int i; for (i = 0; i < NUM_BASES; i++) { policydb_destroy(&bases_met[i]); } for (i = 0; i < NUM_BASES; i++) { policydb_destroy(&bases_notmet[i]); } return 0; } /* This function performs testing of the dependency handles for module global * symbols. It is capable of testing 2 scenarios - the dependencies are met * and the dependencies are not met. * * Paramaters: * req_met boolean indicating whether the base policy meets the * requirements for the modules global block. * b index of the base policy in the global bases_met array. * * policy name of the policy module to load for this test. * decl_type name of the unique type found in the module's global * section is to find that avrule_decl. */ static void do_deps_modreq_global(int req_met, int b, const char *policy, const char *decl_type) { policydb_t *base; policydb_t mod; policydb_t *mods[] = { &mod }; avrule_decl_t *decl; int ret, link_ret; sepol_handle_t *h; /* suppress error reporting - this is because we know that we * are going to get errors and don't want libsepol complaining * about it constantly. */ h = sepol_handle_create(); CU_ASSERT_FATAL(h != NULL); sepol_msg_set_callback(h, NULL, NULL); if (req_met) { base = &bases_met[b]; link_ret = 0; } else { base = &bases_notmet[b]; link_ret = -3; } CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); /* link the modules and check for the correct return value. */ ret = link_modules(h, base, mods, 1, 0); CU_ASSERT_FATAL(ret == link_ret); policydb_destroy(&mod); sepol_handle_destroy(h); if (!req_met) return; decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); CU_ASSERT_FATAL(decl != NULL); CU_ASSERT(decl->enabled == 1); } /* Test that symbol require statements in the global scope of a module * work correctly. This will cover tests 1 - 5 (described above). * * Each of these policies will require as few symbols as possible to * use the required symbol in addition requiring (for example, the type * test also requires an object class for an allow rule). */ static void deps_modreq_global(void) { /* object classes */ do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); /* types */ do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); /* attributes */ do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); /* booleans */ do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); /* roles */ do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); } /* This function performs testing of the dependency handles for module optional * symbols. It is capable of testing 2 scenarios - the dependencies are met * and the dependencies are not met. * * Paramaters: * req_met boolean indicating whether the base policy meets the * requirements for the modules global block. * b index of the base policy in the global bases_met array. * * policy name of the policy module to load for this test. * decl_type name of the unique type found in the module's global * section is to find that avrule_decl. */ static void do_deps_modreq_opt(int req_met, int ret_val, int b, const char *policy, const char *decl_type) { policydb_t *base; policydb_t mod; policydb_t *mods[] = { &mod }; avrule_decl_t *decl; int ret; sepol_handle_t *h; /* suppress error reporting - this is because we know that we * are going to get errors and don't want libsepol complaining * about it constantly. */ h = sepol_handle_create(); CU_ASSERT_FATAL(h != NULL); sepol_msg_set_callback(h, NULL, NULL); if (req_met) { base = &bases_met[b]; } else { base = &bases_notmet[b]; } CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); /* link the modules and check for the correct return value. */ ret = link_modules(h, base, mods, 1, 0); CU_ASSERT_FATAL(ret == ret_val); policydb_destroy(&mod); sepol_handle_destroy(h); if (ret_val < 0) return; decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); CU_ASSERT_FATAL(decl != NULL); if (req_met) { CU_ASSERT(decl->enabled == 1); } else { CU_ASSERT(decl->enabled == 0); } } /* Test that symbol require statements in the global scope of a module * work correctly. This will cover tests 6 - 10 (described above). * * Each of these policies will require as few symbols as possible to * use the required symbol in addition requiring (for example, the type * test also requires an object class for an allow rule). */ static void deps_modreq_opt(void) { /* object classes */ do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); /* types */ do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); /* attributes */ do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); /* booleans */ do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); /* roles */ do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); /* permissions */ do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); } int deps_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { return CU_get_error(); } if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { return CU_get_error(); } return 0; } libsepol/tests/test-deps.h0100644 0000000 0000000 00000002010 13756670065 014651 0ustar000000000 0000000 /* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_DEPS_H__ #define __TEST_DEPS_H__ #include int deps_test_init(void); int deps_test_cleanup(void); int deps_add_tests(CU_pSuite suite); #endif libsepol/tests/test-downgrade.c0100644 0000000 0000000 00000015772 13756670065 015706 0ustar000000000 0000000 /* * Author: Mary Garvin * * Copyright (C) 2007-2008 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-downgrade.h" #include "parse_util.h" #include "helpers.h" #include #include #include #include #include #include #include #include #define POLICY_BIN_HI "policies/test-downgrade/policy.hi" #define POLICY_BIN_LO "policies/test-downgrade/policy.lo" static policydb_t policydb; /* * Function Name: downgrade_test_init * * Input: None * * Output: None * * Description: Initialize the policydb (policy data base structure) */ int downgrade_test_init(void) { /* Initialize the policydb_t structure */ if (policydb_init(&policydb)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); return -1; } return 0; } /* * Function Name: downgrade_test_cleanup * * Input: None * * Output: None * * Description: Destroys policydb structure */ int downgrade_test_cleanup(void) { policydb_destroy(&policydb); return 0; } /* * Function Name: downgrade_add_tests * * Input: CU_pSuite * * Output: Returns 0 upon success. Returns a CUnit error value on failure. * * Description: Add the given downgrade tests to the downgrade suite. */ int downgrade_add_tests(CU_pSuite suite) { if (CU_add_test(suite, "downgrade", test_downgrade) == NULL) return CU_get_error(); return 0; } /* * Function Name: test_downgrade_possible * * Input: None * * Output: None * * Description: * Tests the backward compatability of MLS and Non-MLS binary policy versions. */ void test_downgrade(void) { if (do_downgrade_test(0) < 0) fprintf(stderr, "\nError during downgrade testing of Non-MLS policy\n"); if (do_downgrade_test(1) < 0) fprintf(stderr, "\nError during downgrade testing of MLS policy\n"); } /* * Function Name: do_downgrade_test * * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing * * Output: 0 on success, negative number upon failure * * Description: This function handles the downgrade testing. * A binary policy is read into the policydb structure, the * policy version is decreased by a specific amount, written * back out and then read back in again. The process is * repeated until the minimum policy version is reached. */ int do_downgrade_test(int mls) { policydb_t policydb_tmp; int hi, lo, version; /* Reset policydb for re-use */ policydb_destroy(&policydb); downgrade_test_init(); /* Read in the hi policy from file */ if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) { fprintf(stderr, "error reading %spolicy binary\n", mls ? "mls " : ""); CU_FAIL("Unable to read the binary policy"); return -1; } /* Change MLS value based on parameter */ policydb.mls = mls ? 1 : 0; for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) { /* Stash old version number */ version = policydb.policyvers; /* Try downgrading to each possible version. */ for (lo = hi - 1; lo >= POLICYDB_VERSION_MIN; lo--) { /* Reduce policy version */ policydb.policyvers = lo; /* Write out modified binary policy */ if (write_binary_policy(POLICY_BIN_LO, &policydb) != 0) { /* * Error from MLS to pre-MLS is expected due * to MLS re-implementation in version 19. */ if (mls && lo < POLICYDB_VERSION_MLS) continue; fprintf(stderr, "error writing %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); CU_FAIL("Failed to write downgraded binary policy"); return -1; } /* Make sure we can read back what we wrote. */ if (policydb_init(&policydb_tmp)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); return -1; } if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) != 0) { fprintf(stderr, "error reading %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); CU_FAIL("Unable to read downgraded binary policy"); return -1; } policydb_destroy(&policydb_tmp); } /* Restore version number */ policydb.policyvers = version; } return 0; } /* * Function Name: read_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read binary policy into policydb * structure. */ int read_binary_policy(const char *path, policydb_t *p) { FILE *in_fp = NULL; struct policy_file f; int rc; /* Open the binary policy file */ if ((in_fp = fopen(path, "rb")) == NULL) { fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno)); return -1; } /* Read in the binary policy. */ memset(&f, 0, sizeof(struct policy_file)); f.type = PF_USE_STDIO; f.fp = in_fp; rc = policydb_read(p, &f, 0); fclose(in_fp); return rc; } /* * Function Name: write_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: open file and write the binary policy from policydb structure. */ int write_binary_policy(const char *path, policydb_t *p) { FILE *out_fp = NULL; struct policy_file f; sepol_handle_t *handle; int rc; /* We don't want libsepol to print warnings to stderr */ handle = sepol_handle_create(); if (handle == NULL) { fprintf(stderr, "Out of memory!\n"); return -1; } sepol_msg_set_callback(handle, NULL, NULL); /* Open the binary policy file for writing */ if ((out_fp = fopen(path, "w" )) == NULL) { fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno)); sepol_handle_destroy(handle); return -1; } /* Write the binary policy */ memset(&f, 0, sizeof(struct policy_file)); f.type = PF_USE_STDIO; f.fp = out_fp; f.handle = handle; rc = policydb_write(p, &f); sepol_handle_destroy(f.handle); fclose(out_fp); return rc; } libsepol/tests/test-downgrade.h0100644 0000000 0000000 00000006560 13756670065 015706 0ustar000000000 0000000 /* * Author: Mary Garvin * * Copyright (C) 2007-2008 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_DOWNGRADE_H__ #define __TEST_DOWNGRADE_H__ #include #include /* * Function Name: downgrade_test_init * * Input: None * * Output: None * * Description: Initialize the policydb (policy data base structure) */ int downgrade_test_init(void); /* * Function Name: downgrade_test_cleanup * * Input: None * * Output: None * * Description: Destroys policydb structure */ int downgrade_test_cleanup(void); /* * Function Name: downgrade_add_tests * * Input: CU_pSuite * * Output: Returns 0 upon success. Upon failure, a CUnit testing error * value is returned * * Description: Add the given downgrade tests to the downgrade suite. */ int downgrade_add_tests(CU_pSuite suite); /* * Function Name: test_downgrade_possible * * Input: None * * Output: None * * Description: Tests the backward compatability of MLS and Non-MLS binary * policy versions. */ void test_downgrade(void); /* * Function Name: do_downgrade_test * * Input: int that represents a 0 for Non-MLS policy and a * 1 for MLS policy downgrade testing * * Output: (int) 0 on success, negative number upon failure * * Description: This function handles the downgrade testing. A binary policy * is read into the policydb structure, the policy version is * decreased by a specific amount, written back out and then read * back in again. The process is iterative until the minimum * policy version is reached. */ int do_downgrade_test(int mls); /* * Function Name: read_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read in the binary policy * into the policydb structure. */ int read_binary_policy(const char *path, policydb_t *); /* * Function Name: write_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read in the binary policy * into the policydb structure. */ int write_binary_policy(const char *path, policydb_t *); #endif libsepol/tests/test-expander-attr-map.c0100644 0000000 0000000 00000013642 13756670065 017257 0ustar000000000 0000000 /* * Authors: Chad Sellers * Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-attr-map.h" #include "test-common.h" #include #include #include extern policydb_t base_expanded2; void test_expander_attr_mapping(void) { /* note that many cases are ommitted because they don't make sense (i.e. declaring in an optional and then using it in the base) or because declare in optional then require in a different optional logic still doesn't work */ const char *typesb1[] = { "attr_check_base_1_1_t", "attr_check_base_1_2_t" }; const char *typesb2[] = { "attr_check_base_2_1_t", "attr_check_base_2_2_t" }; const char *typesb3[] = { "attr_check_base_3_1_t", "attr_check_base_3_2_t", "attr_check_base_3_3_t", "attr_check_base_3_4_t" }; const char *typesb4[] = { "attr_check_base_4_1_t", "attr_check_base_4_2_t" }; const char *typesb5[] = { "attr_check_base_5_1_t", "attr_check_base_5_2_t" }; const char *typesb6[] = { "attr_check_base_6_1_t", "attr_check_base_6_2_t", "attr_check_base_6_3_t", "attr_check_base_6_4_t" }; const char *typesbo2[] = { "attr_check_base_optional_2_1_t", "attr_check_base_optional_2_2_t" }; const char *typesbo5[] = { "attr_check_base_optional_5_1_t", "attr_check_base_optional_5_2_t" }; const char *typesm2[] = { "attr_check_mod_2_1_t", "attr_check_mod_2_2_t" }; const char *typesm4[] = { "attr_check_mod_4_1_t", "attr_check_mod_4_2_t" }; const char *typesm5[] = { "attr_check_mod_5_1_t", "attr_check_mod_5_2_t" }; const char *typesm6[] = { "attr_check_mod_6_1_t", "attr_check_mod_6_2_t", "attr_check_mod_6_3_t", "attr_check_mod_6_4_t" }; const char *typesmo2[] = { "attr_check_mod_optional_4_1_t", "attr_check_mod_optional_4_2_t" }; const char *typesb10[] = { "attr_check_base_10_1_t", "attr_check_base_10_2_t" }; const char *typesb11[] = { "attr_check_base_11_3_t", "attr_check_base_11_4_t" }; const char *typesm10[] = { "attr_check_mod_10_1_t", "attr_check_mod_10_2_t" }; const char *typesm11[] = { "attr_check_mod_11_3_t", "attr_check_mod_11_4_t" }; test_attr_types(&base_expanded2, "attr_check_base_1", NULL, typesb1, 2); test_attr_types(&base_expanded2, "attr_check_base_2", NULL, typesb2, 2); test_attr_types(&base_expanded2, "attr_check_base_3", NULL, typesb3, 4); test_attr_types(&base_expanded2, "attr_check_base_4", NULL, typesb4, 2); test_attr_types(&base_expanded2, "attr_check_base_5", NULL, typesb5, 2); test_attr_types(&base_expanded2, "attr_check_base_6", NULL, typesb6, 4); test_attr_types(&base_expanded2, "attr_check_base_optional_2", NULL, typesbo2, 2); test_attr_types(&base_expanded2, "attr_check_base_optional_5", NULL, typesbo5, 2); test_attr_types(&base_expanded2, "attr_check_mod_2", NULL, typesm2, 2); test_attr_types(&base_expanded2, "attr_check_mod_4", NULL, typesm4, 2); test_attr_types(&base_expanded2, "attr_check_mod_5", NULL, typesm5, 2); test_attr_types(&base_expanded2, "attr_check_mod_6", NULL, typesm6, 4); test_attr_types(&base_expanded2, "attr_check_mod_optional_4", NULL, typesmo2, 2); test_attr_types(&base_expanded2, "attr_check_base_7", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_9", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_10", NULL, typesb10, 2); test_attr_types(&base_expanded2, "attr_check_base_11", NULL, typesb11, 2); test_attr_types(&base_expanded2, "attr_check_mod_7", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_9", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_10", NULL, typesm10, 2); test_attr_types(&base_expanded2, "attr_check_mod_11", NULL, typesm11, 2); test_attr_types(&base_expanded2, "attr_check_base_optional_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_optional_7", NULL, NULL, 0); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7_2_t")); } libsepol/tests/test-expander-attr-map.h0100644 0000000 0000000 00000001723 13756670065 017261 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER__ATTR_MAP_H__ #define __TEST_EXPANDER__ATTR_MAP_H__ void test_expander_attr_mapping(void); #endif libsepol/tests/test-expander-roles.c0100644 0000000 0000000 00000002441 13756670065 016651 0ustar000000000 0000000 /* * Authors: Chad Sellers * Joshua Brindle * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-roles.h" #include "test-common.h" #include #include #include extern policydb_t role_expanded; void test_expander_role_mapping(void) { const char *types1[] = { "role_check_1_1_t", "role_check_1_2_t" }; test_role_type_set(&role_expanded, "role_check_1", NULL, types1, 2, 0); } libsepol/tests/test-expander-roles.h0100644 0000000 0000000 00000001772 13756670065 016664 0ustar000000000 0000000 /* * Author: Joshua Brindle * Author: Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_ROLE_H__ #define __TEST_EXPANDER_ROLE_H__ void test_expander_role_mapping(void); #endif libsepol/tests/test-expander-users.c0100644 0000000 0000000 00000004434 13756670065 016672 0ustar000000000 0000000 /* * Authors: Chad Sellers * Joshua Brindle * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-users.h" #include #include #include extern policydb_t user_expanded; static void check_user_roles(policydb_t * p, const char *user_name, const char **role_names, int num_roles) { user_datum_t *user; ebitmap_node_t *tnode; unsigned int i; int j; unsigned char *found; /* array of booleans of roles found */ int extra = 0; /* number of extra roles found */ user = (user_datum_t *) hashtab_search(p->p_users.table, user_name); if (!user) { printf("%s not found\n", user_name); CU_FAIL("user not found"); return; } found = calloc(num_roles, sizeof(unsigned char)); CU_ASSERT_FATAL(found != NULL); ebitmap_for_each_bit(&user->roles.roles, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { extra++; for (j = 0; j < num_roles; j++) { if (strcmp(role_names[j], p->p_role_val_to_name[i]) == 0) { extra--; found[j] += 1; break; } } } } for (j = 0; j < num_roles; j++) { if (found[j] != 1) { printf("role %s associated with user %s %d times\n", role_names[j], user_name, found[j]); CU_FAIL("user mapping failure\n"); } } free(found); CU_ASSERT_EQUAL(extra, 0); } void test_expander_user_mapping(void) { const char *roles1[] = { "user_check_1_1_r", "user_check_1_2_r" }; check_user_roles(&user_expanded, "user_check_1", roles1, 2); } libsepol/tests/test-expander-users.h0100644 0000000 0000000 00000001772 13756670065 016701 0ustar000000000 0000000 /* * Author: Joshua Brindle * Author: Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_USER_H__ #define __TEST_EXPANDER_USER_H__ void test_expander_user_mapping(void); #endif libsepol/tests/test-expander.c0100644 0000000 0000000 00000015374 13756670065 015540 0ustar000000000 0000000 /* * Authors: Chad Sellers * Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This is where the expander tests should go, including: * - check role, type, bool, user mapping * - add symbols declared in enabled optionals * - do not add symbols declared in disabled optionals * - add rules from enabled optionals * - do not add rules from disabled optionals * - verify attribute mapping * - check conditional expressions for correct mapping */ #include "test-expander.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include "test-expander-users.h" #include "test-expander-roles.h" #include "test-expander-attr-map.h" #include #include #include #include #include #include policydb_t role_expanded; policydb_t user_expanded; policydb_t base_expanded2; static policydb_t basemod; static policydb_t basemod2; static policydb_t mod2; static policydb_t base_expanded; static policydb_t base_only_mod; static policydb_t base_only_expanded; static policydb_t role_basemod; static policydb_t role_mod; static policydb_t user_basemod; static policydb_t user_mod; static policydb_t alias_basemod; static policydb_t alias_mod; static policydb_t alias_expanded; static uint32_t *typemap; extern int mls; /* Takes base, some number of modules, links them, and expands them reads source from myfiles array, which has the base string followed by each module string */ int expander_policy_init(policydb_t * mybase, int num_modules, policydb_t ** mymodules, policydb_t * myexpanded, const char *const *myfiles) { char *filename[num_modules + 1]; int i; for (i = 0; i < num_modules + 1; i++) { filename[i] = calloc(PATH_MAX, sizeof(char)); if (snprintf(filename[i], PATH_MAX, "policies/test-expander/%s%s", myfiles[i], mls ? ".mls" : ".std") < 0) return -1; } if (policydb_init(mybase)) { fprintf(stderr, "out of memory!\n"); return -1; } for (i = 0; i < num_modules; i++) { if (policydb_init(mymodules[i])) { fprintf(stderr, "out of memory!\n"); return -1; } } if (policydb_init(myexpanded)) { fprintf(stderr, "out of memory!\n"); return -1; } mybase->policy_type = POLICY_BASE; mybase->mls = mls; if (read_source_policy(mybase, filename[0], myfiles[0])) { fprintf(stderr, "read source policy failed %s\n", filename[0]); return -1; } for (i = 1; i < num_modules + 1; i++) { mymodules[i - 1]->policy_type = POLICY_MOD; mymodules[i - 1]->mls = mls; if (read_source_policy(mymodules[i - 1], filename[i], myfiles[i])) { fprintf(stderr, "read source policy failed %s\n", filename[i]); return -1; } } if (link_modules(NULL, mybase, mymodules, num_modules, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } if (expand_module(NULL, mybase, myexpanded, 0, 0)) { fprintf(stderr, "expand modules failed\n"); return -1; } for (i = 0; i < num_modules + 1; i++) { free(filename[i]); } return 0; } int expander_test_init(void) { const char *small_base_file = "small-base.conf"; const char *base_only_file = "base-base-only.conf"; int rc; policydb_t *mymod2; const char *files2[] = { "small-base.conf", "module.conf" }; const char *role_files[] = { "role-base.conf", "role-module.conf" }; const char *user_files[] = { "user-base.conf", "user-module.conf" }; const char *alias_files[] = { "alias-base.conf", "alias-module.conf" }; rc = expander_policy_init(&basemod, 0, NULL, &base_expanded, &small_base_file); if (rc != 0) return rc; mymod2 = &mod2; rc = expander_policy_init(&basemod2, 1, &mymod2, &base_expanded2, files2); if (rc != 0) return rc; rc = expander_policy_init(&base_only_mod, 0, NULL, &base_only_expanded, &base_only_file); if (rc != 0) return rc; mymod2 = &role_mod; rc = expander_policy_init(&role_basemod, 1, &mymod2, &role_expanded, role_files); if (rc != 0) return rc; /* Just init the base for now, until we figure out how to separate out mls and non-mls tests since users can't be used in mls module */ mymod2 = &user_mod; rc = expander_policy_init(&user_basemod, 0, NULL, &user_expanded, user_files); if (rc != 0) return rc; mymod2 = &alias_mod; rc = expander_policy_init(&alias_basemod, 1, &mymod2, &alias_expanded, alias_files); if (rc != 0) return rc; return 0; } int expander_test_cleanup(void) { policydb_destroy(&basemod); policydb_destroy(&base_expanded); policydb_destroy(&basemod2); policydb_destroy(&base_expanded2); policydb_destroy(&mod2); policydb_destroy(&base_only_mod); policydb_destroy(&base_only_expanded); policydb_destroy(&role_basemod); policydb_destroy(&role_expanded); policydb_destroy(&role_mod); policydb_destroy(&user_basemod); policydb_destroy(&user_expanded); policydb_destroy(&user_mod); policydb_destroy(&alias_basemod); policydb_destroy(&alias_expanded); policydb_destroy(&alias_mod); free(typemap); return 0; } static void test_expander_indexes(void) { test_policydb_indexes(&base_expanded); } static void test_expander_alias(void) { test_alias_datum(&alias_expanded, "alias_check_1_a", "alias_check_1_t", 1, 0); test_alias_datum(&alias_expanded, "alias_check_2_a", "alias_check_2_t", 1, 0); test_alias_datum(&alias_expanded, "alias_check_3_a", "alias_check_3_t", 1, 0); } int expander_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "expander_indexes", test_expander_indexes)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_attr_mapping", test_expander_attr_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_role_mapping", test_expander_role_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_user_mapping", test_expander_user_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_alias", test_expander_alias)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } libsepol/tests/test-expander.h0100644 0000000 0000000 00000002032 13756670066 015531 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_H__ #define __TEST_EXPANDER_H__ #include int expander_test_init(void); int expander_test_cleanup(void); int expander_add_tests(CU_pSuite suite); #endif libsepol/tests/test-linker-cond-map.c0100644 0000000 0000000 00000012064 13756670066 016704 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include #include /* Tests for conditionals * Test each cond/bool for these * - boolean copied correctly (state is correct) * - conditional expression is correct * Tests: * - single boolean in base * - single boolean in module * - single boolean in base optional * - single boolean in module optional * - 2 booleans in base * - 2 booleans in module * - 2 booleans in base optional * - 2 booleans in module optional * - 2 booleans, base and module * - 2 booleans, base optional and module * - 2 booleans, base optional and module optional * - 3 booleans, base, base optional, module * - 4 boolean, base, base optional, module, module optional */ typedef struct test_cond_expr { const char *bool; uint32_t expr_type; } test_cond_expr_t; void test_cond_expr_mapping(policydb_t * p, avrule_decl_t * d, test_cond_expr_t * bools, int len) { int i; cond_expr_t *expr; CU_ASSERT_FATAL(d->cond_list != NULL); CU_ASSERT_FATAL(d->cond_list->expr != NULL); expr = d->cond_list->expr; for (i = 0; i < len; i++) { CU_ASSERT_FATAL(expr != NULL); CU_ASSERT(expr->expr_type == bools[i].expr_type); if (bools[i].bool) { CU_ASSERT(strcmp(p->sym_val_to_name[SYM_BOOLS][expr->bool - 1], bools[i].bool) == 0); } expr = expr->next; } } void test_bool_state(policydb_t * p, const char *bool, int state) { cond_bool_datum_t *b; b = hashtab_search(p->p_bools.table, bool); CU_ASSERT_FATAL(b != NULL); CU_ASSERT(b->state == state); } void base_cond_tests(policydb_t * base) { avrule_decl_t *d; unsigned int decls[1]; test_cond_expr_t bools[2]; /* these tests look at booleans and conditionals in the base only * to ensure that they aren't altered or removed during the link process */ /* bool existance and state, global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"); decls[0] = d->decl_id; test_sym_presence(base, "g_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_b_bool_1", 0); /* conditional expression mapped correctly */ bools[0].bool = "g_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existance and state, optional scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); decls[0] = d->decl_id; test_sym_presence(base, "o1_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_b_bool_1", 1); /* conditional expression mapped correctly */ bools[0].bool = "o1_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); } void module_cond_tests(policydb_t * base) { avrule_decl_t *d; unsigned int decls[1]; test_cond_expr_t bools[3]; /* bool existance and state, module 1 global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"); decls[0] = d->decl_id; test_sym_presence(base, "g_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_m1_bool_1", 1); /* conditional expression mapped correctly */ bools[0].bool = "g_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existance and state, module 1 optional scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o1_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_m1_bool_1", 0); /* conditional expression mapped correctly */ bools[0].bool = "o1_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existance and state, module 2 global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"); decls[0] = d->decl_id; test_sym_presence(base, "g_m2_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_sym_presence(base, "g_m2_bool_2", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_m2_bool_1", 1); test_bool_state(base, "g_m2_bool_2", 0); /* conditional expression mapped correctly */ bools[0].bool = "g_m2_bool_1"; bools[0].expr_type = COND_BOOL; bools[1].bool = "g_m2_bool_2"; bools[1].expr_type = COND_BOOL; bools[2].bool = NULL; bools[2].expr_type = COND_AND; test_cond_expr_mapping(base, d, bools, 3); } libsepol/tests/test-linker-cond-map.h0100644 0000000 0000000 00000002010 13756670066 016677 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_COND_MAP_H__ #define __TEST_LINKER_COND_MAP_H__ extern void base_cond_tests(policydb_t * base); extern void module_cond_tests(policydb_t * base); #endif libsepol/tests/test-linker-roles.c0100644 0000000 0000000 00000021470 13756670066 016333 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include /* Tests for roles: * Test for each of these for * - role in appropriate symtab (global and decl) * - datum in the decl symtab has correct type_set * - scope datum has correct decl ids * - dominates bitmap is correct * Tests: * - role in base, no modules * - role in base optional, no modules * - role a in base, b in module * - role a in base and module (additive) * - role a in base and 2 module * - role a in base optional, b in module * - role a in base, b in module optional * - role a in base optional, b in module optional * - role a in base optional and module * - role a in base and module optional * - role a in base optional and module optional * - role a in base optional and 2 modules * - role a and b in base, b dom a, are types correct (TODO) */ /* this simply tests whether the passed in role only has its own * value in its dominates ebitmap */ static void only_dominates_self(policydb_t * p, role_datum_t * role) { ebitmap_node_t *tnode; unsigned int i; int found = 0; ebitmap_for_each_bit(&role->dominates, tnode, i) { if (ebitmap_node_get_bit(tnode, i)) { found++; CU_ASSERT(i == role->s.value - 1); } } CU_ASSERT(found == 1); } void base_role_tests(policydb_t * base) { avrule_decl_t *decl; role_datum_t *role; unsigned int decls[2]; const char *types[2]; /* These tests look at roles in the base only, the desire is to ensure that * roles are not destroyed or otherwise removed during the link process */ /**** test for g_b_role_1 in base and decl 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_b_type_1, no negset, no flags) */ types[0] = "g_b_type_1"; role = test_role_type_set(base, "g_b_role_1", NULL, types, 1, 0); /* This role should only dominate itself */ only_dominates_self(base, role); /**** test for o1_b_role_1 in optional (decl 2) ****/ decl = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); decls[0] = decl->decl_id; test_sym_presence(base, "o1_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (o1_b_type_1, no negset, no flags) */ types[0] = "o1_b_type_1"; role = test_role_type_set(base, "o1_b_role_1", decl, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); } void module_role_tests(policydb_t * base) { role_datum_t *role; avrule_decl_t *decl; unsigned int decls[3]; const char *types[3]; /* These tests are run when the base is linked with 2 modules, * They should test whether the roles get copied correctly from the * modules into the base */ /**** test for role in module 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_m1_type_1, no negset, no flags) */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "g_m1_role_1", NULL, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in module 1 (optional) ****/ decl = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); decls[0] = decl->decl_id; test_sym_presence(base, "o1_m1_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (o1_m1_type_1, no negset, no flags) */ types[0] = "o1_m1_type_1"; role = test_role_type_set(base, "o1_m1_role_1", decl, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /* These test whether the type sets are copied to the right place and * correctly unioned when they should be */ /**** test for type added to base role in module 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_role_2", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_m1_type_1, no negset, no flags) */ types[0] = "g_b_type_2"; /* added in base when declared */ types[1] = "g_m1_type_1"; /* added in module */ role = test_role_type_set(base, "g_b_role_2", NULL, types, 2, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for type added to base role in module 1 & 2 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; decls[2] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"))->decl_id; test_sym_presence(base, "g_b_role_3", SYM_ROLES, SCOPE_DECL, decls, 3); /* make sure it has the correct type set (g_b_type_2, g_m1_type_2, g_m2_type_2, no negset, no flags) */ types[0] = "g_b_type_2"; /* added in base when declared */ types[1] = "g_m1_type_2"; /* added in module 1 */ types[2] = "g_m2_type_2"; /* added in module 2 */ role = test_role_type_set(base, "g_b_role_3", NULL, types, 3, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base optional and module 1 (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "o1_b_role_2", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the global symtab and one in the base optional 1 */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "o1_b_role_2", NULL, types, 1, 0); types[0] = "o1_b_type_1"; role = test_role_type_set(base, "o1_b_role_2", test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m1"))->decl_id; test_sym_presence(base, "g_b_role_4", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the global symtab and one in the base optional 1 */ types[0] = "g_b_type_2"; role = test_role_type_set(base, "g_b_role_4", NULL, types, 1, 0); types[0] = "g_m1_type_2"; role = test_role_type_set(base, "g_b_role_4", test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m1"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"))->decl_id; test_sym_presence(base, "o3_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the 3rd base optional and one in the 3rd module optional */ types[0] = "o3_b_type_1"; role = test_role_type_set(base, "o3_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_b"), types, 1, 0); types[0] = "o3_m1_type_1"; role = test_role_type_set(base, "o3_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; decls[2] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"))->decl_id; test_sym_presence(base, "o4_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 3); /* this one will have 2 type sets, one in the global symtab (with both module types) and one in the 4th optional of base */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "o4_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"), types, 1, 0); types[0] = "g_m2_type_1"; types[1] = "g_m1_type_2"; role = test_role_type_set(base, "o4_b_role_1", NULL, types, 2, 0); /* and only dominates itself */ only_dominates_self(base, role); } libsepol/tests/test-linker-roles.h0100644 0000000 0000000 00000002050 13756670066 016331 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_ROLES_H__ #define __TEST_LINKER_ROLES_H__ #include extern void base_role_tests(policydb_t * base); extern void module_role_tests(policydb_t * base); #endif libsepol/tests/test-linker-types.c0100644 0000000 0000000 00000035225 13756670066 016356 0ustar000000000 0000000 /* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include /* Tests for types: * Test for each of these for * - type in appropriate symtab (global and decl) * - datum in the decl symtab has correct type bitmap (if attr) * - primary is set correctly * - scope datum has correct decl ids * Tests: * - type in base, no modules * - type in base optional, no modules * - type a in base, b in module * - type a in base optional, b in module * - type a in base, b in module optional * - type a in base optional, b in module optional * - attr in base, no modules * - attr in base optional, no modules * - attr a in base, b in module * - attr a in base optional, b in module * - attr a in base, b in module optional * - attr a in base optional, b in module optional * - attr a declared in base, added to in module * - attr a declared in base, added to in module optional * - attr a declared in base, added to in 2 modules * - attr a declared in base, added to in 2 modules (optional and global) * - attr a declared in base optional, added to in module * - attr a declared in base optional, added to in module optional * - attr a added to in base optional, declared in module * - attr a added to in base optional, declared in module optional * - attr a added to in base optional, declared in module, added to in other module * - attr a added to in base optional, declared in module optional, added to in other module * - attr a added to in base optional, declared in module , added to in other module optional * - attr a added to in base optional, declared in module optional, added to in other module optional * - alias in base of primary type in base, no modules * - alias in base optional of primary type in base, no modules * - alias in base optional of primary type in base optional * - alias in module of primary type in base * - alias in module optional of primary type in base * - alias in module optional of primary type in base optional * - alias in module of primary type in module * - alias in module optional of primary type in module * - alias in module optional of primary type in module optional * - alias a in base, b in module, primary type in base * - alias a in base, b in module, primary type in module * - alias a in base optional, b in module, primary type in base * - alias a in base optional, b in module, primary type in module * - alias a in base, b in module optional, primary type in base * - alias a in base, b in module optional, primary type in module * - alias a in base optional, b in module optional, primary type in base * - alias a in base optional, b in module optional, primary type in module * - alias a in base, required in module, primary type in base * - alias a in base, required in base optional, primary type in base * - alias a in base, required in module optional, primary type in base * - alias a in module, required in base optional, primary type in base * - alias a in module, required in module optional, primary type in base * - alias a in base optional, required in module, primary type in base * - alias a in base optional, required in different base optional, primary type in base * - alias a in base optional, required in module optional, primary type in base * - alias a in module optional, required in base optional, primary type in base * - alias a in module optional, required in module optional, primary type in base * - alias a in module, required in base optional, primary type in module * - alias a in module, required in module optional, primary type in module * - alias a in base optional, required in module, primary type in module * - alias a in base optional, required in different base optional, primary type in module * - alias a in base optional, required in module optional, primary type in module * - alias a in module optional, required in base optional, primary type in module * - alias a in module optional, required in module optional, primary type in module */ /* Don't pass in decls from global blocks since symbols aren't stored in their symtab */ static void test_type_datum(policydb_t * p, const char *id, unsigned int *decls, int len, unsigned int primary) { int i; unsigned int value; type_datum_t *type; /* just test the type datums for each decl to see if it is what we expect */ type = hashtab_search(p->p_types.table, id); CU_ASSERT_FATAL(type != NULL); CU_ASSERT(type->primary == primary); CU_ASSERT(type->flavor == TYPE_TYPE); value = type->s.value; for (i = 0; i < len; i++) { type = hashtab_search(p->decl_val_to_struct[decls[i] - 1]->p_types.table, id); CU_ASSERT_FATAL(type != NULL); CU_ASSERT(type->primary == primary); CU_ASSERT(type->flavor == TYPE_TYPE); CU_ASSERT(type->s.value == value); } } void base_type_tests(policydb_t * base) { unsigned int decls[2]; const char *types[2]; /* These tests look at types in the base only, the desire is to ensure that * types are not destroyed or otherwise removed during the link process. * if this happens these tests won't work anyway since we are using types to * mark blocks */ /**** test for g_b_type_1 in base and decl 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "g_b_type_1", NULL, 0, 1); /* this attr is in the same decl as the type */ test_sym_presence(base, "g_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_b_type_1"; test_attr_types(base, "g_b_attr_1", NULL, types, 1); /**** test for o1_b_type_1 in optional (decl 2) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; test_sym_presence(base, "o1_b_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "o1_b_type_1", NULL, 0, 1); /* this attr is in the same decl as the type */ test_sym_presence(base, "o1_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o1_b_type_1"; test_attr_types(base, "o1_b_attr_1", base->decl_val_to_struct[decls[0] - 1], types, 1); /* tests for aliases */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_alias_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_b_alias_1", "g_b_type_3", 1, 0); decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o6_b"))->decl_id; test_sym_presence(base, "g_b_alias_2", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_b_alias_2", "g_b_type_3", 1, 0); } void module_type_tests(policydb_t * base) { unsigned int decls[2]; const char *types[2]; avrule_decl_t *d; /* These tests look at types that were copied from modules or attributes * that were modified and declared in modules and base. These apply to * declarations and modifications in and out of optionals. These tests * should ensure that types and attributes are correctly copied from modules * and that attribute type sets are correctly copied and mapped. */ /* note: scope for attributes is currently smashed if the attribute is declared * somewhere so the scope test only looks at global, the type bitmap test looks * at the appropriate decl symtab */ /* test for type in module 1 (global) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "g_m1_type_1", NULL, 0, 1); /* attr has is in the same decl as the above type */ test_sym_presence(base, "g_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_1"; types[1] = "g_m1_type_2"; test_attr_types(base, "g_m1_attr_1", NULL, types, 2); /* test for type in module 1 (optional) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"))->decl_id; test_sym_presence(base, "o1_m1_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "o1_m1_type_1", NULL, 0, 1); /* attr has is in the same decl as the above type */ test_sym_presence(base, "o1_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o1_m1_type_2"; test_attr_types(base, "o1_m1_attr_1", base->decl_val_to_struct[decls[0] - 1], types, 1); /* test for attr declared in base, added to in module (global). * Since these are both global it'll be merged in the main symtab */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_3", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_3"; test_attr_types(base, "g_b_attr_3", NULL, types, 1); /* test for attr declared in base, added to in module (optional). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_4", SYM_TYPES, SCOPE_DECL, decls, 1); decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"))->decl_id; types[0] = "o1_m1_type_3"; test_attr_types(base, "g_b_attr_4", base->decl_val_to_struct[decls[0] - 1], types, 1); /* test for attr declared in base, added to in 2 modules (global). (merged in main symtab) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_5", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_4"; types[1] = "g_m2_type_4"; test_attr_types(base, "g_b_attr_5", NULL, types, 2); /* test for attr declared in base, added to in 2 modules (optional/global). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_6", SYM_TYPES, SCOPE_DECL, decls, 1); /* module 2 was global to its type is in main symtab */ types[0] = "g_m2_type_5"; test_attr_types(base, "g_b_attr_6", NULL, types, 1); d = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1")); types[0] = "o3_m1_type_2"; test_attr_types(base, "g_b_attr_6", d, types, 1); /* test for attr declared in base optional, added to in module (global). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"))->decl_id; test_sym_presence(base, "o4_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_5"; test_attr_types(base, "o4_b_attr_1", NULL, types, 1); /* test for attr declared in base optional, added to in module (optional). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; test_sym_presence(base, "o1_b_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); types[0] = "o1_m1_type_5"; test_attr_types(base, "o1_b_attr_2", d, types, 1); /* test for attr declared in module, added to in base optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); types[0] = "o1_b_type_2"; test_attr_types(base, "g_m1_attr_2", d, types, 1); /* test for attr declared in module optional, added to in base optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"))->decl_id; test_sym_presence(base, "o3_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"); types[0] = "o4_b_type_1"; test_attr_types(base, "o3_m1_attr_1", d, types, 1); /* attr a added to in base optional, declared/added to in module, added to in other module */ /* first the module declare/add and module 2 add (since its global it'll be in the main symtab */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_3", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_6"; types[1] = "g_m2_type_3"; test_attr_types(base, "g_m1_attr_3", NULL, types, 2); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"); types[0] = "o4_b_type_2"; test_attr_types(base, "g_m1_attr_3", d, types, 1); /* attr a added to in base optional, declared/added in module optional, added to in other module */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o3_m1_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o3_m1_type_3"; test_attr_types(base, "o3_m1_attr_2", d, types, 1); /* module 2's type will be in the main symtab */ types[0] = "g_m2_type_6"; test_attr_types(base, "o3_m1_attr_2", NULL, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_b"); types[0] = "o2_b_type_1"; test_attr_types(base, "o3_m1_attr_2", d, types, 1); /* attr a added to in base optional, declared/added in module , added to in other module optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_4", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_7"; test_attr_types(base, "g_m1_attr_4", NULL, types, 1); /* module 2 */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m2"); types[0] = "o2_m2_type_1"; test_attr_types(base, "g_m1_attr_4", d, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o5_b"); types[0] = "o5_b_type_1"; test_attr_types(base, "g_m1_attr_4", d, types, 1); /* attr a added to in base optional, declared/added in module optional, added to in other module optional */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o4_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o4_m1_type_1"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* module 2 */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m2"); types[0] = "o2_m2_type_2"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o5_b"); types[0] = "o5_b_type_2"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* tests for aliases */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m_alias_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_m_alias_1", "g_b_type_3", 1, 0); } libsepol/tests/test-linker-types.h0100644 0000000 0000000 00000002002 13756670066 016346 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_TYPES_H__ #define __TEST_LINKER_TYPES_H__ extern void base_type_tests(policydb_t * base); extern void module_type_tests(policydb_t * base); #endif libsepol/tests/test-linker.c0100644 0000000 0000000 00000007333 13756670066 015213 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This is where the linker tests should go, including: * - check role, type, bool, user, attr mapping * - check for properly enabled optional * - check for properly disabled optional * - check for non-optional disabled blocks * - properly add symbols declared in optionals */ #include "test-linker.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include "test-linker-roles.h" #include "test-linker-types.h" #include "test-linker-cond-map.h" #include #include #include #include #include #include #define NUM_MODS 2 #define NUM_POLICIES NUM_MODS+1 #define BASEMOD NUM_MODS const char *policies[NUM_POLICIES] = { "module1.conf", "module2.conf", "small-base.conf", }; static policydb_t basenomods; static policydb_t linkedbase; static policydb_t *modules[NUM_MODS]; extern int mls; int linker_test_init(void) { int i; if (test_load_policy(&linkedbase, POLICY_BASE, mls, "test-linker", policies[BASEMOD])) return -1; if (test_load_policy(&basenomods, POLICY_BASE, mls, "test-linker", policies[BASEMOD])) return -1; for (i = 0; i < NUM_MODS; i++) { modules[i] = calloc(1, sizeof(*modules[i])); if (!modules[i]) { fprintf(stderr, "out of memory!\n"); return -1; } if (test_load_policy(modules[i], POLICY_MOD, mls, "test-linker", policies[i])) return -1; } if (link_modules(NULL, &linkedbase, modules, NUM_MODS, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } if (link_modules(NULL, &basenomods, NULL, 0, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } return 0; } int linker_test_cleanup(void) { int i; policydb_destroy(&basenomods); policydb_destroy(&linkedbase); for (i = 0; i < NUM_MODS; i++) { policydb_destroy(modules[i]); free(modules[i]); } return 0; } static void test_linker_indexes(void) { test_policydb_indexes(&linkedbase); } static void test_linker_roles(void) { base_role_tests(&basenomods); base_role_tests(&linkedbase); module_role_tests(&linkedbase); } static void test_linker_types(void) { base_type_tests(&basenomods); base_type_tests(&linkedbase); module_type_tests(&linkedbase); } static void test_linker_cond(void) { base_cond_tests(&basenomods); base_cond_tests(&linkedbase); module_cond_tests(&linkedbase); } int linker_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "linker_indexes", test_linker_indexes)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_types", test_linker_types)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_roles", test_linker_roles)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_cond", test_linker_cond)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } libsepol/tests/test-linker.h0100644 0000000 0000000 00000002020 13756670066 015204 0ustar000000000 0000000 /* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_H__ #define __TEST_LINKER_H__ #include int linker_test_init(void); int linker_test_cleanup(void); int linker_add_tests(CU_pSuite suite); #endif libsepol/utils/0040755 0000000 0000000 00000000000 13756670066 012601 5ustar000000000 0000000 libsepol/utils/Makefile0100644 0000000 0000000 00000000662 13756670066 014242 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin CFLAGS ?= -Wall -Werror override CFLAGS += -I../include override LDFLAGS += -L../src override LDLIBS += -lsepol TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c))) all: $(TARGETS) install: all -mkdir -p $(DESTDIR)$(BINDIR) install -m 755 $(TARGETS) $(DESTDIR)$(BINDIR) clean: -rm -f $(TARGETS) *.o indent: ../../scripts/Lindent $(wildcard *.[ch]) relabel: libsepol/utils/chkcon.c0100644 0000000 0000000 00000001442 13756670066 014210 0ustar000000000 0000000 #include #include #include #include #include #include #include void usage(char*) __attribute__((noreturn)); void usage(char *progname) { printf("usage: %s policy context\n", progname); exit(1); } int main(int argc, char **argv) { FILE *fp; if (argc != 3) usage(argv[0]); fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open '%s': %s\n", argv[1], strerror(errno)); exit(1); } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing %s: %s\n", argv[1], strerror(errno)); exit(1); } fclose(fp); if (sepol_check_context(argv[2]) < 0) { fprintf(stderr, "%s is not valid\n", argv[2]); exit(1); } printf("%s is valid\n", argv[2]); exit(0); } mcstrans/0040755 0000000 0000000 00000000000 13756670066 011462 5ustar000000000 0000000 mcstrans/COPYING0100644 0000000 0000000 00000043110 13756670066 012511 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mcstrans/Makefile0100644 0000000 0000000 00000000352 13756670066 013117 0ustar000000000 0000000 all: $(MAKE) -C src $(MAKE) -C utils install: $(MAKE) -C src install # $(MAKE) -C utils install $(MAKE) -C man install clean: rm -f *~ \#* $(MAKE) -C src clean $(MAKE) -C utils clean $(MAKE) -C man clean relabel: test: mcstrans/TODO0100644 0000000 0000000 00000000771 13756670066 012154 0ustar000000000 0000000 TODO List for mcstrans: In compute_raw_from_trans look for conflicting bit patterns and report errors. In emit_whitespace look at whitespace characters for any regex special character and escape them. Make prefixes and suffixes optional (ex. SECRET REL AUS == SECRET AUS). compute_trans_from_raw is an expensive operation that needs to be sped up or threaded so that mcstrans can respond to other requests more quickly. Reevaluate the means of determining whether inverse bits are used in a domain. mcstrans/VERSION0100644 0000000 0000000 00000000004 13756670066 012521 0ustar000000000 0000000 2.9 mcstrans/man/0040755 0000000 0000000 00000000000 13756670066 012235 5ustar000000000 0000000 mcstrans/man/Makefile0100644 0000000 0000000 00000000776 13756670066 013704 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN8SUBDIR ?= man8 MAN8DIR ?= $(MANDIR)/$(MAN8SUBDIR) all: install: all mkdir -p $(DESTDIR)$(MAN8DIR) install -m 644 man8/*.8 $(DESTDIR)$(MAN8DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man8 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ install -m 644 $${lang}/man8/*.8 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ fi ; \ done clean: -rm -f *~ \#* -rm -f man8/*~ man8/\#* mcstrans/man/man8/0040755 0000000 0000000 00000000000 13756670066 013100 5ustar000000000 0000000 mcstrans/man/man8/mcs.80100644 0000000 0000000 00000002351 13756670066 013751 0ustar000000000 0000000 .TH "mcs" "8" "8 Sep 2005" "dwalsh@redhat.com" "mcs documentation" .SH "NAME" mcs \- Multi-Category System .SH "DESCRIPTION" MCS (Multiple Category System) allows users to label files on their system within administrator defined categories. It then uses SELinux Mandatory Access Control to protect those files. MCS is a discretionary model to allow users to mark their data with additional tags that further restrict access. The only mandatory aspect is authorizing users for categories by defining their clearance in policy. However, MCS is similar to MLS and exercises the same code paths and share the same support infrastructure. They just differ in their specific configuration. The .I /etc/selinux/{SELINUXTYPE}/setrans.conf configuration file translates the labels on disk to human readable form. Administrators can define any labels they want in this file. Certain applications like printing and auditing will use these labels to identify the files. By setting a category on a file you will prevent other applications/services from having access to the files. .P Examples of file labels would be PatientRecord, CompanyConfidential etc. .SH "SEE ALSO" selinux(8), chcon(1) .SH FILES /etc/selinux/{SELINUXTYPE}/setrans.conf mcstrans/man/man8/mcstransd.80100644 0000000 0000000 00000001600 13756670066 015161 0ustar000000000 0000000 .TH "mcstransd" "8" "16 Oct 2009" "dwalsh@redhat.com" "mcs documentation" .SH "NAME" mcstransd \- MCS (Multiple Category System) daemon. Translates SELinux MCS/MLS labels to human readable form. .SH "SYNOPSIS" .B mcstransd [-f] [-h] .P .SH "DESCRIPTION" This manual page describes the .BR mcstransd program. .P This daemon reads /etc/selinux/{SELINUXTYPE}/setrans.conf configuration file, and communicates with libselinux via a socket in /var/run/setrans. .SH "OPTIONS" .TP \-f Run mcstransd in the foreground. Do not run as a daemon. .TP \-h Output a short summary of available command line options\&. .SH "AUTHOR" This man page was written by Dan Walsh . The program was originally written by Dan Walsh . The program was enhanced/rewritten by Joe Nall . .SH "FILES" /etc/selinux/{SELINUXTYPE}/setrans.conf .SH "SEE ALSO" .BR mcs (8), mcstrans/man/man8/setrans.conf.80100644 0000000 0000000 00000006427 13756670066 015602 0ustar000000000 0000000 .TH "setrans.conf" "8" "13 July 2010" "txtoth@gmail.com" "setrans.conf documentation" .SH "NAME" setrans.conf \- translation configuration file for MCS/MLS SELinux systems .SH "DESCRIPTION" The .I /etc/selinux/{SELINUXTYPE}/setrans.conf configuration file specifies the way that SELinux MCS/MLS labels are translated into human readable form by the mcstransd daemon. The default policies support 16 sensitivity levels (s0 through s15) and 1024 categories (c0 through c1023). Multiple categories can be separated with commas (c0,c1,c3,c5) and a range of categories can be shortened using dot notation (c0.c3,c5). .SS "Keywords" .TP Base\fR once a base is declared, subsequent sensitivity label definitions will have all modifiers applied to them during translation. Sensitivity labels defined before the base declaration are immediately cached and no modifiers will be applied these are used as direct translations. .TP Default\fR defines the category bit range that will be used for inverse bits. .TP Domain\fR creates a new domain with the supplied name. .TP Include\fR read and process the contents of the specified configuration file. .TP Join\fR defines a character used to separate members of a modifier group when more than one is specified (ex. USA/AUS). .TP ModifierGroup\fR a means of grouping category bit definitions by how they modify the sensitivity label. .TP Prefix\fR word(s) that may proceed member(s) of a modifier group (ex. REL USA). .TP Suffix\fR word(s) that may follow member(s) of a modifier group (ex. USA EYES ONLY). .TP Whitespace\fR defines the set of acceptable white space characters that may be used in label being translated. .SS "Sensitivity Level Definition Examples" .TP s0=SystemLow\fR defines a translation of s0 (the lowest sensitivity level) with no categories to SystemLow. .TP s15:c0.c1023=SystemHigh\fR defines a translation of s15:c0.c1023 to SystemHigh. c0.c1023 is shorthand for all categories. A colon separates the sensitivity level and categories. .TP s0\-s15:c0.c1023=SystemLow\-SystemHigh\fR defines a range translation of s0\-s15:c0.c1023 to SystemLow\-SystemHigh. The two range components are separated by a dash. .TP s0:c0=PatientRecord\fR defines a translation of sensitivity s0 with category c0 to PatientRecord. .TP s0:c1=Accounting\fR defines a translation of sensitivity s0 with category c1 to Accounting. .TP s2:c1,c2,c3=Confidential3Categories .TP s2:c1.c3=Confidential3Categories\fR both define a translation of sensitivity s2 with categories c1, c2 and c3 to Confidential3Categories. .TP s5=TopSecret\fR defines a translation of sensitivity s5 with no categories to TopSecret. .SS "Constraint Examples" .TP c0!c1 if category bits 0 and 1 are both set, the constraint will fail and the original context will be returned. .TP c5.c9>c1 if category bits 5 through 9 are set, bit 1 must also be set or the constraint will fail and the original context will be returned. .TP s1!c5,c9 if category bits 5 and 9 are set and the sensitivity level is s1, the constraint will fail and the original context will be returned. .SH "AUTHOR" Written by Joe Nall . Updated by Ted X. Toth . .SH "SEE ALSO" selinux(8), mcs(8), mls(8), chcon(1) .SH "FILES" /etc/selinux/{SELINUXTYPE}/setrans.conf .br /usr/share/mcstrans/examples mcstrans/man/ru/0040755 0000000 0000000 00000000000 13756670066 012663 5ustar000000000 0000000 mcstrans/man/ru/man8/0040755 0000000 0000000 00000000000 13756670066 013526 5ustar000000000 0000000 mcstrans/man/ru/man8/mcs.80100644 0000000 0000000 00000004705 13756670066 014404 0ustar000000000 0000000 .TH "mcs" "8" "8 сентября 2005" "dwalsh@redhat.com" "Документация по MCS" .SH "ИМЯ" mcs \- мультикатегорийная система .SH "ОПИСАНИЕ" MCS (мультикатегорийная система) позволяет пользователям проставлять в своей системе метки для файлов внутри определённых администратором категорий. Затем эта система использует принудительное управление доступом SELinux, чтобы защитить эти файлы. MCS - дискреционная модель, которая позволяет пользователям отмечать свои данные дополнительными тегами, накладывая дальнейшие ограничения доступа. Обязательным является только один аспект - авторизовывать пользователей для категорий, определяя их уровень допуска в политике. MCS похожа на MLS, выполняет те же самые пути кода и использует ту же самую инфраструктуру поддержки. Они отличаются между собой только спецификой настройки. Файл конфигурации .I /etc/selinux/{SELINUXTYPE}/setrans.conf преобразовывает метки на диске в удобную для прочтения человеком форму. В этом файле администраторы могут определить любые необходимые метки. Некоторые приложения, такие как вывод на экран и аудит, будут использовать эти метки для идентификации файлов. Если для файла будет задана категория, другие приложения/службы не получат к нему доступ. .P Примеры меток файлов: PatientRecord, CompanyConfidential и так далее. .SH "СМОТРИТЕ ТАКЖЕ" selinux(8), chcon(1) .SH ФАЙЛЫ /etc/selinux/{SELINUXTYPE}/setrans.conf .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся mcstrans/man/ru/man8/mcstransd.80100644 0000000 0000000 00000003020 13756670066 015605 0ustar000000000 0000000 .TH "mcstransd" "8" "16 октября 2009" "dwalsh@redhat.com" "Документация по MCS" .SH "ИМЯ" mcstransd \- внутренняя служба MCS (мультикатегорийная система). Переводит метки MCS/MLS SELinux в удобную для прочтения человеком форму. .SH "ОБЗОР" .B mcstransd [-f] [-h] .P .SH "ОПИСАНИЕ" Эта страница руководства содержит описание программы .BR mcstransd. .P Эта внутренняя служба выполняет чтение файла конфигурации /etc/selinux/{SELINUXTYPE}/setrans.conf и связывается с libselinux через сокет в /var/run/setrans. .SH "ПАРАМЕТРЫ" .TP \-f Запустить mcstransd на переднем плане. Не запускать как внутреннюю службу. .TP \-h Вывести краткое описание доступных параметров командной строки\&. .SH "ФАЙЛЫ" /etc/selinux/{SELINUXTYPE}/setrans.conf .SH "СМОТРИТЕ ТАКЖЕ" .BR mcs (8) .SH "АВТОРЫ" Эта man-страница написана Dan Walsh . Исходная версия программы написана Dan Walsh . Программа улучшена/переписана Joe Nall . Перевод на русский язык выполнила Герасименко Олеся . mcstrans/man/ru/man8/setrans.conf.80100644 0000000 0000000 00000013553 13756670066 016226 0ustar000000000 0000000 .TH "setrans.conf" "8" "13 июля 2010" "txtoth@gmail.com" "Документация по setrans.conf" .SH "ИМЯ" setrans.conf \- файл конфигурации преобразования для систем MCS/MLS SELinux .SH "ОПИСАНИЕ" Файл конфигурации .I /etc/selinux/{SELINUXTYPE}/setrans.conf определяет способ, которым метки SELinux MCS/MLS преобразовываются в удобную для прочтения человеком форму с помощью внутренней службы mcstransd. Политики по умолчанию поддерживают 16 уровней конфиденциальности (от s0 до s15) и 1024 категории (от c0 до c1023). Если категорий несколько, их можно разделить запятыми (c0,c1,c3,c5), а диапазон категорий - сократить с помощью указания через точку (c0.c3,c5). .SS "Ключевые слова" .TP Base\fR когда объявляется база, ко всем последующим определениям меток конфиденциальности будут при преобразовании применяться модификаторы. Метки конфиденциальности, которые были определены до объявления базы, незамедлительно кэшируются, и к ним не применяются модификаторы; они используются в качестве прямого преобразования. .TP Default\fR определяет битовый диапазон категорий, который будет использоваться для обратных битов. .TP Domain\fR создаёт новый домен с указанным именем. .TP Include\fR прочитать и обработать содержимое указанного файла конфигурации. .TP Join\fR определяет символ, который используется для разделения участников группы модификаторов, когда указано более одного (например, USA/AUS). .TP ModifierGroup\fR средство группировки битовых определений категорий по тому, как они изменяют метку конфиденциальности. .TP Prefix\fR слова (слова), которое может предшествовать участнику (участникам) группы модификаторов (например, REL USA). .TP Suffix\fR слово (слова), которое может следовать за участником (участниками) группы модификаторов (например, USA EYES ONLY). .TP Whitespace\fR определяет набор допустимых пробельных символов, которые могут использоваться в преобразовываемой метке. .SS "Примеры определения уровня конфиденциальности" .TP s0=SystemLow\fR определяет преобразование s0 (минимального уровня конфиденциальности) без категорий в SystemLow. .TP s15:c0.c1023=SystemHigh\fR определяет преобразование s15:c0.c1023 в SystemHigh. c0.c1023 - сокращённое обозначение всех категорий. Уровень конфиденциальности и категории разделены двоеточием. .TP s0\-s15:c0.c1023=SystemLow\-SystemHigh\fR определяет преобразование диапазона s0\-s15:c0.c1023 в SystemLow\-SystemHigh. Два компонента диапазона разделены дефисом. .TP s0:c0=PatientRecord\fR определяет преобразование уровня конфиденциальности s0 с категорией c0 в PatientRecord. .TP s0:c1=Accounting\fR определяет преобразование уровня конфиденциальности s0 с категорией c1 в Accounting. .TP s2:c1,c2,c3=Confidential3Categories .TP s2:c1.c3=Confidential3Categories\fR и то, и другое определяет преобразование уровня конфиденциальности s2 с категориями c1, c2 и c3 в Confidential3Categories. .TP s5=TopSecret\fR определяет преобразование уровня конфиденциальности s5 без категорий в TopSecret. .SS "Примеры ограничения" .TP c0!c1 если одновременно заданы биты категорий 0 и 1, ограничение не сработает и будет возвращён исходный контекст. .TP c5.c9>c1 если заданы биты категорий с 5 по 9, бит 1 также необходимо установить - иначе ограничение не сработает и будет возвращён исходный контекст. .TP s1!c5,c9 если заданы биты категорий с 5 по 9 и уровень конфиденциальности равен s1, ограничение не сработает и будет возвращён исходный контекст. .SH "ФАЙЛЫ" /etc/selinux/{SELINUXTYPE}/setrans.conf .br /usr/share/mcstrans/examples .SH "СМОТРИТЕ ТАКЖЕ" selinux(8), mcs(8), mls(8), chcon(1) .SH "АВТОРЫ" Написано Joe Nall . Обновлено Ted X. Toth . Перевод на русский язык выполнила Герасименко Олеся . mcstrans/share/0040755 0000000 0000000 00000000000 13756670066 012564 5ustar000000000 0000000 mcstrans/share/examples/0040755 0000000 0000000 00000000000 13756670066 014402 5ustar000000000 0000000 mcstrans/share/examples/default/0040755 0000000 0000000 00000000000 13756670066 016026 5ustar000000000 0000000 mcstrans/share/examples/default/README0100644 0000000 0000000 00000000270 13756670066 016702 0ustar000000000 0000000 Original RHEL 5 setrans.conf To use: cp setrans.conf /etc/selinux/mls/setrans.conf run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlstrans-test default.test mcstrans/share/examples/default/default.test0100644 0000000 0000000 00000001360 13756670066 020350 0ustar000000000 0000000 SystemLow==s0 SystemHigh==s15:c0.c1023 SystemLow-SystemHigh==s0-s15:c0.c1023 Unclassified==s1 Secret==s2 A==s2:c0 B==s2:c1 SystemLow-Unclassified==s0-s1 Unclassified-Secret==s1-s2 Unclassified-SystemHigh==s1-s15:c0.c1023 SystemLow-Secret==s0-s2 SystemLow-Secret:A==s0-s2:c0 SystemLow-Secret:B==s0-s2:c1 SystemLow-Secret:AB==s0-s2:c0,c1 Unclassified-Secret:A==s1-s2:c0 Unclassified-Secret:B==s1-s2:c1 Unclassified-Secret:AB==s1-s2:c0,c1 Secret-Secret:A==s2-s2:c0 Secret-Secret:B==s2-s2:c1 Secret-Secret:AB==s2-s2:c0,c1 Secret-SystemHigh==s2-s15:c0.c1023 Secret:A-Secret:AB==s2:c0-s2:c0,c1 Secret:A-SystemHigh==s2:c0-s15:c0.c1023 Secret:B-Secret:AB==s2:c1-s2:c0,c1 Secret:B-SystemHigh==s2:c1-s15:c0.c1023 Secret:AB-SystemHigh==s2:c0,c1-s15:c0.c1023 mcstrans/share/examples/default/setrans.conf0100644 0000000 0000000 00000002534 13756670066 020355 0ustar000000000 0000000 # # Multi-Level Security translation table for SELinux # # Uncomment the following to disable translation libary # disable=1 # # Objects can be labeled with one of 16 levels and be categorized with 0-1023 # categories defined by the admin. # Objects can be in more than one category at a time. # Users can modify this table to translate the MLS labels for different purpose. # # Assumptions: using below MLS labels. # SystemLow # SystemHigh # Unclassified # Secret with compartments A and B. # # SystemLow and SystemHigh s0=SystemLow s15:c0.c1023=SystemHigh s0-s15:c0.c1023=SystemLow-SystemHigh # Unclassified level s1=Unclassified # Secret level with compartments s2=Secret s2:c0=A s2:c1=B # ranges for Unclassified s0-s1=SystemLow-Unclassified s1-s2=Unclassified-Secret s1-s15:c0.c1023=Unclassified-SystemHigh # ranges for Secret with compartments s0-s2=SystemLow-Secret s0-s2:c0=SystemLow-Secret:A s0-s2:c1=SystemLow-Secret:B s0-s2:c0,c1=SystemLow-Secret:AB s1-s2:c0=Unclassified-Secret:A s1-s2:c1=Unclassified-Secret:B s1-s2:c0,c1=Unclassified-Secret:AB s2-s2:c0=Secret-Secret:A s2-s2:c1=Secret-Secret:B s2-s2:c0,c1=Secret-Secret:AB s2-s15:c0.c1023=Secret-SystemHigh s2:c0-s2:c0,c1=Secret:A-Secret:AB s2:c0-s15:c0.c1023=Secret:A-SystemHigh s2:c1-s2:c0,c1=Secret:B-Secret:AB s2:c1-s15:c0.c1023=Secret:B-SystemHigh s2:c0,c1-s15:c0.c1023=Secret:AB-SystemHigh mcstrans/share/examples/include/0040755 0000000 0000000 00000000000 13756670066 016025 5ustar000000000 0000000 mcstrans/share/examples/include/README0100644 0000000 0000000 00000000411 13756670066 016676 0ustar000000000 0000000 Original RHEL 5 setrans.conf pushed into setrans.d as include file To use: cp setrans.conf /etc/selinux/mls/setrans.conf cp setrans.d/* /etc/selinux/mls/setrans.d run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlstrans-test include.test mcstrans/share/examples/include/default.test0100644 0000000 0000000 00000001360 13756670066 020347 0ustar000000000 0000000 SystemLow==s0 SystemHigh==s15:c0.c1023 SystemLow-SystemHigh==s0-s15:c0.c1023 Unclassified==s1 Secret==s2 A==s2:c0 B==s2:c1 SystemLow-Unclassified==s0-s1 Unclassified-Secret==s1-s2 Unclassified-SystemHigh==s1-s15:c0.c1023 SystemLow-Secret==s0-s2 SystemLow-Secret:A==s0-s2:c0 SystemLow-Secret:B==s0-s2:c1 SystemLow-Secret:AB==s0-s2:c0,c1 Unclassified-Secret:A==s1-s2:c0 Unclassified-Secret:B==s1-s2:c1 Unclassified-Secret:AB==s1-s2:c0,c1 Secret-Secret:A==s2-s2:c0 Secret-Secret:B==s2-s2:c1 Secret-Secret:AB==s2-s2:c0,c1 Secret-SystemHigh==s2-s15:c0.c1023 Secret:A-Secret:AB==s2:c0-s2:c0,c1 Secret:A-SystemHigh==s2:c0-s15:c0.c1023 Secret:B-Secret:AB==s2:c1-s2:c0,c1 Secret:B-SystemHigh==s2:c1-s15:c0.c1023 Secret:AB-SystemHigh==s2:c0,c1-s15:c0.c1023 mcstrans/share/examples/include/setrans.conf0100644 0000000 0000000 00000000756 13756670066 020360 0ustar000000000 0000000 # # Multi-Level Security translation table for SELinux # # Uncomment the following to disable translation libary # disable=1 # # Objects can be labeled with one of 16 levels and be categorized with 0-1023 # categories defined by the admin. # Objects can be in more than one category at a time. # Users can modify this table to translate the MLS labels for different purpose. # # Demonstrate Include by moving everthing to an include file # Include=/etc/selinux/mls/setrans.d/include-example mcstrans/share/examples/include/setrans.d/0040755 0000000 0000000 00000000000 13756670066 017726 5ustar000000000 0000000 mcstrans/share/examples/include/setrans.d/include-example0100644 0000000 0000000 00000002534 13756670066 022726 0ustar000000000 0000000 # # Multi-Level Security translation table for SELinux # # Uncomment the following to disable translation libary # disable=1 # # Objects can be labeled with one of 16 levels and be categorized with 0-1023 # categories defined by the admin. # Objects can be in more than one category at a time. # Users can modify this table to translate the MLS labels for different purpose. # # Assumptions: using below MLS labels. # SystemLow # SystemHigh # Unclassified # Secret with compartments A and B. # # SystemLow and SystemHigh s0=SystemLow s15:c0.c1023=SystemHigh s0-s15:c0.c1023=SystemLow-SystemHigh # Unclassified level s1=Unclassified # Secret level with compartments s2=Secret s2:c0=A s2:c1=B # ranges for Unclassified s0-s1=SystemLow-Unclassified s1-s2=Unclassified-Secret s1-s15:c0.c1023=Unclassified-SystemHigh # ranges for Secret with compartments s0-s2=SystemLow-Secret s0-s2:c0=SystemLow-Secret:A s0-s2:c1=SystemLow-Secret:B s0-s2:c0,c1=SystemLow-Secret:AB s1-s2:c0=Unclassified-Secret:A s1-s2:c1=Unclassified-Secret:B s1-s2:c0,c1=Unclassified-Secret:AB s2-s2:c0=Secret-Secret:A s2-s2:c1=Secret-Secret:B s2-s2:c0,c1=Secret-Secret:AB s2-s15:c0.c1023=Secret-SystemHigh s2:c0-s2:c0,c1=Secret:A-Secret:AB s2:c0-s15:c0.c1023=Secret:A-SystemHigh s2:c1-s2:c0,c1=Secret:B-Secret:AB s2:c1-s15:c0.c1023=Secret:B-SystemHigh s2:c0,c1-s15:c0.c1023=Secret:AB-SystemHigh mcstrans/share/examples/nato/0040755 0000000 0000000 00000000000 13756670066 015343 5ustar000000000 0000000 mcstrans/share/examples/nato/README0100644 0000000 0000000 00000000544 13756670066 016223 0ustar000000000 0000000 NATO example test setrans.conf To use: mkdir /etc/selinux/mls/mcstrand.d cp rel.conf /etc/selinux/mls/mcstrand.d cp eyes-only.conf /etc/selinux/mls/mcstrand.d cp constraints.conf /etc/selinux/mls/mcstrand.d cp setrans.conf /etc/selinux/mls/setrans.conf sudo run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlstrans-test nato.test mcstrans/share/examples/nato/nato.test0100644 0000000 0000000 00000001613 13756670066 017203 0ustar000000000 0000000 NATO CONFIDENTIAL==s4:c1,c200.c511 CONFIDENTIAL-NATO SECRET!=s4:c0,c2,c11,c200.c511-s5:c1,c200.c511 NATO SECRET REL NATO==s5:c1,c201.c204,c206.c218,c220.c222,c224.c238,c240.c256,c259,c260,c262.c267,c270.c273,c275.c277,c279.c287,c289.c297,c299,c301.c307,c309,c311.c330,c334.c364,c367.c377,c379,c380,c382.c386,c388.c405,c408.c422,c424.c429,c431.c511 NATO CONFIDENTIAL NATO EYES ONLY==s4:c1,c200.c204,c206.c218,c220.c222,c224.c238,c240.c256,c259,c260,c262.c267,c270.c273,c275.c277,c279.c287,c289.c297,c299,c301.c307,c309,c311.c330,c334.c364,c367.c377,c379,c380,c382.c386,c388.c405,c408.c422,c424.c429,c431.c511 NATO CONFIDENTIAL-NATO SECRET==s4:c1,c200.c511-s5:c1,c200.c511 NATO CONFIDENTIAL REL AUS/US-NATO SECRET REL AUS/US==s4:c1,c201.c214,c216.c429,c431.c511-s5:c1,c201.c214,c216.c429,c431.c511 NATO CONFIDENTIAL DEU EYES ONLY-NATO SECRET DEU EYES ONLY==s4:c1,c200.c257,c259.c511-s5:c1,c200.c257,c259.c511 mcstrans/share/examples/nato/setrans.conf0100644 0000000 0000000 00000001024 13756670066 017663 0ustar000000000 0000000 # UNCLASSIFIED Domain=NATOEXAMPLE s0=SystemLow s15:c0.c1023=SystemHigh s0-s15:c0.c1023=SystemLow-SystemHigh Base=Sensitivity Levels s1=UNCLASSIFIED s3:c0,c2,c11,c200.c511=RESTRICTED s4:c0,c2,c11,c200.c511=CONFIDENTIAL s5:c0,c2,c11,c200.c511=SECRET s1:c1=NATO UNCLASSIFIED s3:c1,c200.c511=NATO RESTRICTED s4:c1,c200.c511=NATO CONFIDENTIAL s5:c1,c200.c511=NATO SECRET Include=/etc/selinux/mls/setrans.d/rel.conf Include=/etc/selinux/mls/setrans.d/eyes-only.conf Include=/etc/selinux/mls/setrans.d/constraints.conf # UNCLASSIFIED mcstrans/share/examples/nato/setrans.d/0040755 0000000 0000000 00000000000 13756670066 017244 5ustar000000000 0000000 mcstrans/share/examples/nato/setrans.d/constraints.conf0100644 0000000 0000000 00000000247 13756670066 022462 0ustar000000000 0000000 # UNCLASSIFIED # These constraints apply to computed translations, # not cached or preset translations. # # nato and non-nato are incompatible c0!c1 #UNCLASSIFIED mcstrans/share/examples/nato/setrans.d/eyes-only.conf0100644 0000000 0000000 00000041077 13756670066 022045 0ustar000000000 0000000 #UNCLASSIFIED ModifierGroup=Eyes Only Whitespace=- ,/ Join=/ Suffix=EYES ONLY Default=c200.c511 ~c205,~c219,~c223,~c239,~c257,~c258,~c261,~c268,~c269,~c274,~c278,~c288,~c298,~c300,~c308,~c310,~c331,~c332,~c333,~c365,~c366,~c378,~c381,~c387,~c406,~c407,~c423,~c430=NATO # Aruba - bit 201 ~c201=AA # Aruba ~c201=ABW # Aruba # Antigua and Barbuda - bit 214 ~c214=AC # Antigua and Barbuda ~c214=ATG # Antigua and Barbuda # United Arab Emirates - bit 208 #~c208=AE # United Arab Emirates ~c208=ARE # United Arab Emirates # Afghanistan - bit 202 ~c202=AF # Afghanistan ~c202=AFG # Afghanistan # Algeria - bit 263 ~c263=AG # Algeria ~c263=DZA # Algeria # Azerbaijan - bit 217 ~c217=AJ # Azerbaijan ~c217=AZE # Azerbaijan # Albania - bit 205 ~c205=AL # Albania ~c205=ALB # Albania # Armenia - bit 210 ~c210=AM # Armenia ~c210=ARM # Armenia # Andorra - bit 206 ~c206=AN # Andorra ~c206=AND # Andorra # Angola - bit 203 ~c203=AO # Angola ~c203=AGO # Angola # American Samoa - bit 211 ~c211=AQ # American Samoa ~c211=ASM # American Samoa # Argentina - bit 209 ~c209=AR # Argentina ~c209=ARG # Argentina # Australia - bit 215 ~c215=AUS # Australia ~c215=AS # Australia # Austria - bit 216 ~c216=AU # Austria ~c216=AUT # Austria # Anguilla - bit 204 ~c204=AV # Anguilla ~c204=AIA # Anguilla # Antarctica - bit 212 ~c212=AY # Antarctica ~c212=ATA # Antarctica # Bahrain - bit 224 ~c224=BA # Bahrain ~c224=BHR # Bahrain # Barbados - bit 233 ~c233=BB # Barbados ~c233=BRB # Barbados # Botswana - bit 237 ~c237=BC # Botswana ~c237=BWA # Botswana # Bermuda - bit 230 ~c230=BD # Bermuda ~c230=BMU # Bermuda # Belgium - bit 219 ~c219=BE # Belgium ~c219=BEL # Belgium # Bahamas, The - bit 225 ~c225=BF # Bahamas, The ~c225=BHS # Bahamas, The # Bangladesh - bit 222 ~c222=BG # Bangladesh ~c222=BGD # Bangladesh # Belize - bit 229 ~c229=BH # Belize ~c229=BLZ # Belize # Bosnia and Herzegovina - bit 226 ~c226=BK # Bosnia and Herzegovina ~c226=BIH # Bosnia and Herzegovina # Bolivia - bit 231 ~c231=BL # Bolivia ~c231=BOL # Bolivia # Burma - bit 346 ~c346=BM # Burma ~c346=MMR # Burma # Benin - bit 220 ~c220=BN # Benin ~c220=BEN # Benin # Belarus - bit 228 ~c228=BO # Belarus ~c228=BLR # Belarus # Solomon Islands - bit 397 ~c397=BP # Solomon Islands ~c397=SLB # Solomon Islands # Brazil - bit 232 ~c232=BR # Brazil ~c232=BRA # Brazil # Bhutan - bit 235 ~c235=BT # Bhutan ~c235=BTN # Bhutan # Bulgaria - bit 223 ~c223=BU # Bulgaria ~c223=BGR # Bulgaria # Bouvet Island - bit 236 ~c236=BV # Bouvet Island ~c236=BVT # Bouvet Island # Brunei - bit 234 ~c234=BX # Brunei ~c234=BRN # Brunei # Burundi - bit 218 ~c218=BY # Burundi ~c218=BDI # Burundi # Canada - bit 239 ~c239=CA # Canada ~c239=CAN # Canada # Cambodia - bit 318 ~c318=CB # Cambodia ~c318=KHM # Cambodia # Chad - bit 413 ~c413=CD # Chad ~c413=TCD # Chad # Sri Lanka - bit 329 ~c329=CE # Sri Lanka ~c329=LKA # Sri Lanka # Congo, Republic of the - bit 247 ~c247=CF # Congo, Republic of the ~c247=COG # Congo, Republic of the # Congo, Democratic Republic of the - bit 246 ~c246=CG # Congo, Democratic Republic of the ~c246=COD # Congo, Democratic Republic of the # China - bit 243 ~c243=CH # China ~c243=CHN # China # Chile - bit 242 ~c242=CI # Chile ~c242=CHL # Chile # Cayman Islands - bit 255 ~c255=CJ # Cayman Islands ~c255=CYM # Cayman Islands # Cocos (Keeling) Islands - bit 240 part of AUS ~c240=CK # Cocos (Keeling) Islands ~c240=CCK # Cocos (Keeling) Islands # Cameroon - bit 245 ~c245=CM # Cameroon ~c245=CMR # Cameroon # Comoros - bit 250 ~c250=CN # Comoros ~c250=COM # Comoros # Colombia - bit 249 ~c249=CO # Colombia ~c249=COL # Colombia # Northern Mariana Islands - bit 349 ~c349=CQ # Northern Mariana Islands ~c349=MNP # Northern Mariana Islands # Costa Rica - bit 252 ~c252=CS # Costa Rica ~c252=CRI # Costa Rica # Central African Republic - bit 238 ~c238=CT # Central African Republic ~c238=CAF # Central African Republic # Cuba - bit 253 ~c253=CU # Cuba ~c253=CUB # Cuba # Cape Verde - bit 251 ~c251=CV # Cape Verde ~c251=CPV # Cape Verde # Cook Islands - bit 248 ~c248=CW # Cook Islands ~c248=COK # Cook Islands # Cyprus - bit 256 ~c256=CY # Cyprus ~c256=CYP # Cyprus # Denmark - bit 261 ~c261=DA # Denmark ~c261=DNK # Denmark # Djibouti - bit 259 ~c259=DJ # Djibouti ~c259=DJI # Djibouti # Dominica - bit 260 ~c260=DO # Dominica ~c260=DMA # Dominica # Dominican Republic - bit 262 ~c262=DR # Dominican Republic ~c262=DOM # Dominican Republic # Ecuador - bit 264 ~c264=EC # Ecuador ~c264=ECU # Ecuador # Egypt - bit 265 ~c265=EG # Egypt ~c265=EGY # Egypt # Ireland - bit 305 ~c305=EI # Ireland ~c305=IRL # Ireland # Equatorial Guinea - bit 287 ~c287=EK # Equatorial Guinea ~c287=GNQ # Equatorial Guinea # Estonia - bit 269 ~c269=EN # Estonia ~c269=EST # Estonia # Eritrea - bit 266 ~c266=ER # Eritrea ~c266=ERI # Eritrea # El Salvador - bit 399 ~c399=ES # El Salvador ~c399=SLV # El Salvador # Ethiopia - bit 270 ~c270=ET # Ethiopia ~c270=ETH # Ethiopia # Czech Republic - bit 257 #~c257=EZ # Czech Republic ~c257=CZE # Czech Republic # French Guiana - bit 292 ~c292=FG # French Guiana ~c292=GUF # French Guiana # Finland - bit 271 ~c271=FI # Finland ~c271=FIN # Finland # Fiji - bit 272 ~c272=FJ # Fiji ~c272=FJI # Fiji # Falkland Islands (Islas Malvinas) - bit 273 ~c273=FK # Falkland Islands (Islas Malvinas) ~c273=FLK # Falkland Islands (Islas Malvinas) # Micronesia, Federated States of - bit 276 ~c276=FM # Micronesia, Federated States of ~c276=FSM # Micronesia, Federated States of # Faroe Islands - bit 275 ~c275=FO # Faroe Islands ~c275=FRO # Faroe Islands # French Polynesia - bit 384 ~c384=FP # French Polynesia ~c384=PYF # French Polynesia # France - bit 274 ~c274=FR # France ~c274=FRA # France # French Southern and Antarctic Lands - bit 213 ~c213=FS # French Southern and Antarctic Lands ~c213=ATF # French Southern and Antarctic Lands # Gambia, The - bit 285 ~c285=GA # Gambia, The ~c285=GMB # Gambia, The # Gabon - bit 277 ~c277=GB # Gabon ~c277=GAB # Gabon # Georgia - bit 279 ~c279=GG # Georgia ~c279=GEO # Georgia # Ghana - bit 281 ~c281=GH # Ghana ~c281=GHA # Ghana # Gibraltar - bit 282 ~c282=GI # Gibraltar ~c282=GIB # Gibraltar # Grenada - bit 289 ~c289=GJ # Grenada ~c289=GRD # Grenada # Guernsey - bit 280 part of UK ~c280=GK # Guernsey ~c280=GGY # Guernsey # Greenland - bit 290 ~c290=GL # Greenland ~c290=GRL # Greenland # Germany - bit 258 #~c258=GM # Germany ~c258=DEU # Germany # Guadeloupe - bit 284 ~c284=GP # Guadeloupe ~c284=GLP # Guadeloupe # Guam - bit 293 ~c293=GQ # Guam ~c293=GUM # Guam # Greece - bit 288 ~c288=GR # Greece ~c288=GRC # Greece # Guatemala - bit 291 ~c291=GT # Guatemala ~c291=GTM # Guatemala # Guinea - bit 283 ~c283=GV # Guinea ~c283=GIN # Guinea # Guyana - bit 294 ~c294=GY # Guyana ~c294=GUY # Guyana # Gaza Strip - bit 383 #~c383=GZ # Gaza Strip ~c383=PSE # Gaza Strip # Haiti - bit 299 ~c299=HA # Haiti ~c299=HTI # Haiti # Hong Kong - bit 295 ~c295=HK # Hong Kong ~c295=HKG # Hong Kong # Heard Island and McDonald Islands - bit 296 ~c296=HM # Heard Island and McDonald Islands ~c296=HMD # Heard Island and McDonald Islands # Honduras - bit 297 ~c297=HO # Honduras ~c297=HND # Honduras # Croatia - bit 298 ~c298=HR # Croatia ~c298=HRV # Croatia # Hungary - bit 300 ~c300=HU # Hungary ~c300=HUN # Hungary # Iceland - bit 308 ~c308=IC # Iceland ~c308=ISL # Iceland # Indonesia - bit 301 ~c301=ID # Indonesia ~c301=IDN # Indonesia # Isle of Man - bit 302 part of UK ~c302=IM # Isle of Man ~c302=IMN # Isle of Man # India - bit 303 ~c303=IN # India ~c303=IND # India # British Indian Ocean Territory - bit 304 ~c304=IO # British Indian Ocean Territory ~c304=IOT # British Indian Ocean Territory # Iran - bit 306 ~c306=IR # Iran ~c306=IRN # Iran # Israel - bit 309 ~c309=IS # Israel ~c309=ISR # Israel # Italy - bit 310 ~c310=IT # Italy ~c310=ITA # Italy # Cote d'Ivoire - bit 244 ~c244=IV # Cote d'Ivoire ~c244=CIV # Cote d'Ivoire # Iraq - bit 307 ~c307=IZ # Iraq ~c307=IRQ # Iraq # Japan - bit 314 ~c314=JA # Japan ~c314=JPN # Japan # Jersey - bit 312 part of UK ~c312=JE # Jersey ~c312=JEY # Jersey # Jamaica - bit 311 ~c311=JM # Jamaica ~c311=JAM # Jamaica # Jordan - bit 313 ~c313=JO # Jordan ~c313=JOR # Jordan # Kenya - bit 316 ~c316=KE # Kenya ~c316=KEN # Kenya # Kyrgyzstan - bit 317 ~c317=KG # Kyrgyzstan ~c317=KGZ # Kyrgyzstan # Korea, North - bit 380 ~c380=KN # Korea, North ~c380=PRK # Korea, North # Kiribati - bit 319 ~c319=KR # Kiribati ~c319=KIR # Kiribati # Korea, South - bit 321 ~c321=KS # Korea, South ~c321=ROK # Korea, South # Christmas Island - bit 254 ~c254=KT # Christmas Island ~c254=CXR # Christmas Island # Kuwait - bit 322 ~c322=KU # Kuwait ~c322=KWT # Kuwait # Kazakhstan - bit 315 ~c315=KZ # Kazakhstan ~c315=KAZ # Kazakhstan # Laos - bit 323 ~c323=LA # Laos ~c323=LAO # Laos # Lebanon - bit 324 ~c324=LE # Lebanon ~c324=LBN # Lebanon # Latvia - bit 333 ~c333=LG # Latvia ~c333=LVA # Latvia # Lithuania - bit 331 ~c331=LH # Lithuania ~c331=LTU # Lithuania # Liberia - bit 325 ~c325=LI # Liberia ~c325=LBR # Liberia # Slovakia - bit 406 ~c406=LO # Slovakia ~c406=SVK # Slovakia # Liechtenstein - bit 328 ~c328=LS # Liechtenstein ~c328=LIE # Liechtenstein # Lesotho - bit 330 ~c330=LT # Lesotho ~c330=LSO # Lesotho # Luxembourg - bit 332 ~c332=LU # Luxembourg ~c332=LUX # Luxembourg # Libya - bit 326 ~c326=LY # Libya ~c326=LBY # Libya # Madagascar - bit 339 ~c339=MA # Madagascar ~c339=MDG # Madagascar # Martinique - bit 353 ~c353=MB # Martinique ~c353=MTQ # Martinique # Macau - bit 334 ~c334=MC # Macau ~c334=MAC # Macau # Moldova - bit 338 ~c338=MD # Moldova ~c338=MDA # Moldova # Mayotte - bit 357 part of FRA ~c357=MF # Mayotte ~c357=MYT # Mayotte # Mongolia - bit 348 ~c348=MG # Mongolia ~c348=MNG # Mongolia # Montserrat - bit 352 ~c352=MH # Montserrat ~c352=MSR # Montserrat # Malawi - bit 355 ~c355=MI # Malawi ~c355=MWI # Malawi # Montenegro - bit 347 ~c347=MJ # Montenegro ~c347=MNE # Montenegro # Macedonia - bit 343 part of FYR ~c343=MK # Macedonia ~c343=MKD # Macedonia # Mali - bit 344 ~c344=ML # Mali ~c344=MLI # Mali # Monaco - bit 337 ~c337=MN # Monaco ~c337=MCO # Monaco # Morocco - bit 336 ~c336=MO # Morocco ~c336=MAR # Morocco # Mauritius - bit 354 ~c354=MP # Mauritius ~c354=MUS # Mauritius # Mauritania - bit 351 ~c351=MR # Mauritania ~c351=MRT # Mauritania # Malta - bit 345 ~c345=MT # Malta ~c345=MLT # Malta # Oman - bit 370 ~c370=MU # Oman ~c370=OMN # Oman # Maldives - bit 340 ~c340=MV # Maldives ~c340=MDV # Maldives # Mexico - bit 341 ~c341=MX # Mexico ~c341=MEX # Mexico # Malaysia - bit 356 ~c356=MY # Malaysia ~c356=MYS # Malaysia # Mozambique - bit 350 ~c350=MZ # Mozambique ~c350=MOZ # Mozambique # New Caledonia - bit 359 ~c359=NC # New Caledonia ~c359=NCL # New Caledonia # Niue - bit 364 ~c364=NE # Niue ~c364=NIU # Niue # Norfolk Island - bit 361 ~c361=NF # Norfolk Island ~c361=NFK # Norfolk Island # Niger - bit 360 ~c360=NG # Niger ~c360=NER # Niger # Vanuatu - bit 438 ~c438=NH # Vanuatu ~c438=VUT # Vanuatu # Nigeria - bit 362 ~c362=NI # Nigeria ~c362=NGA # Nigeria # Netherlands - bit 365 ~c365=NL # Netherlands ~c365=NLD # Netherlands # Norway - bit 366 ~c366=NO # Norway ~c366=NOR # Norway # Nepal - bit 367 ~c367=NP # Nepal ~c367=NPL # Nepal # Nauru - bit 368 ~c368=NR # Nauru ~c368=NRU # Nauru # Suriname - bit 405 ~c405=NS # Suriname ~c405=SUR # Suriname # Netherlands Antilles - bit 207 ~c207=NT # Netherlands Antilles ~c207=ANT # Netherlands Antilles # Nicaragua - bit 363 ~c363=NU # Nicaragua ~c363=NIC # Nicaragua # New Zealand - bit 369 ~c369=NZ # New Zealand ~c369=NZL # New Zealand # Paraguay - bit 382 ~c382=PA # Paraguay ~c382=PRY # Paraguay # Pitcairn Islands - bit 373 ~c373=PC # Pitcairn Islands ~c373=PCN # Pitcairn Islands # Peru - bit 374 ~c374=PE # Peru ~c374=PER # Peru # Pakistan - bit 371 ~c371=PK # Pakistan ~c371=PAK # Pakistan # Poland - bit 378 ~c378=PL # Poland ~c378=POL # Poland # Panama - bit 372 ~c372=PM # Panama ~c372=PAN # Panama # Portugal - bit 381 ~c381=PO # Portugal ~c381=PRT # Portugal # Papua New Guinea - bit 377 ~c377=PP # Papua New Guinea ~c377=PNG # Papua New Guinea # Palau - bit 376 #~c376=PS # Palau ~c376=PLW # Palau # Guinea-Bissau - bit 286 ~c286=PU # Guinea-Bissau ~c286=GNB # Guinea-Bissau # Qatar - bit 385 ~c385=QA # Qatar ~c385=QAT # Qatar # Serbia - bit 403 #~c403=RB # Serbia ~c403=SRB # Serbia # Reunion - bit 386 ~c386=RE # Reunion ~c386=REU # Reunion # Marshall Islands - bit 342 ~c342=RM # Marshall Islands ~c342=MHL # Marshall Islands # Saint Martin - bit 335 ~c335=RN # Saint Martin ~c335=MAF # Saint Martin # Romania - bit 387 ~c387=RO # Romania ~c387=ROU # Romania # Philippines - bit 375 ~c375=RP # Philippines ~c375=PHL # Philippines # Puerto Rico - bit 379 ~c379=RQ # Puerto Rico ~c379=PRI # Puerto Rico # Russia - bit 388 #~c388=RS # Russia ~c388=RUS # Russia # Rwanda - bit 389 ~c389=RW # Rwanda ~c389=RWA # Rwanda # Saudi Arabia - bit 390 ~c390=SA # Saudi Arabia ~c390=SAU # Saudi Arabia # Saint Pierre and Miquelon - bit 402 ~c402=SB # Saint Pierre and Miquelon ~c402=SPM # Saint Pierre and Miquelon # Saint Kitts and Nevis - bit 320 ~c320=SC # Saint Kitts and Nevis ~c320=KNA # Saint Kitts and Nevis # Seychelles - bit 410 ~c410=SE # Seychelles ~c410=SYC # Seychelles # South Africa - bit 442 ~c442=SF # South Africa ~c442=ZAF # South Africa # Senegal - bit 392 ~c392=SG # Senegal ~c392=SEN # Senegal # Saint Helena - bit 395 ~c395=SH # Saint Helena ~c395=SHN # Saint Helena # Slovenia - bit 407 #~c407=SI # Slovenia ~c407=SVN # Slovenia # Sierra Leone - bit 398 ~c398=SL # Sierra Leone ~c398=SLE # Sierra Leone # San Marino - bit 400 ~c400=SM # San Marino ~c400=SMR # San Marino # Singapore - bit 393 ~c393=SN # Singapore ~c393=SGP # Singapore # Somalia - bit 401 ~c401=SO # Somalia ~c401=SOM # Somalia # Spain - bit 268 #~c268=SP # Spain ~c268=ESP # Spain # Saint Lucia - bit 327 ~c327=ST # Saint Lucia ~c327=LCA # Saint Lucia # Sudan - bit 391 ~c391=SU # Sudan ~c391=SDN # Sudan # Svalbard - bit 396 #~c396=SV # Svalbard ~c396=SJM # Svalbard # Sweden - bit 408 ~c408=SW # Sweden ~c408=SWE # Sweden # South Georgia and the Islands - bit 394 ~c394=SX # South Georgia and the Islands ~c394=SGS # South Georgia and the Islands # Syria - bit 411 ~c411=SY # Syria ~c411=SYR # Syria # Switzerland - bit 241 ~c241=SZ # Switzerland ~c241=CHE # Switzerland # Saint Barthelemy - bit 227 ~c227=TB # Saint Barthelemy ~c227=BLM # Saint Barthelemy # Trinidad and Tobago - bit 421 ~c421=TD # Trinidad and Tobago ~c421=TTO # Trinidad and Tobago # Thailand - bit 415 ~c415=TH # Thailand ~c415=THA # Thailand # Tajikistan - bit 416 ~c416=TI # Tajikistan ~c416=TJK # Tajikistan # Turks and Caicos Islands - bit 412 ~c412=TK # Turks and Caicos Islands ~c412=TCA # Turks and Caicos Islands # Togo - bit 414 ~c414=TGO # Tokelau - bit 417 ~c417=TL # Tokelau ~c417=TKL # Tokelau # Tonga - bit 420 ~c420=TN # Tonga ~c420=TON # Tonga # Togo - bit 414 ~c414=TO # Togo ~c414=TGO # Togo # Sao Tome and Principe - bit 404 ~c404=TP # Sao Tome and Principe ~c404=STP # Sao Tome and Principe # Tunisia - bit 422 ~c422=TS # Tunisia ~c422=TUN # Tunisia # Timor-Leste - bit 419 ~c419=TT # Timor-Leste ~c419=TLS # Timor-Leste # Turkey - bit 423 ~c423=TU # Turkey ~c423=TUR # Turkey # Tuvalu - bit 424 ~c424=TV # Tuvalu ~c424=TUV # Tuvalu # Taiwan - bit 425 ~c425=TW # Taiwan ~c425=TWN # Taiwan # Turkmenistan - bit 418 ~c418=TX # Turkmenistan ~c418=TKM # Turkmenistan # Tanzania - bit 426 ~c426=TZ # Tanzania ~c426=TZA # Tanzania # Uganda - bit 427 ~c427=UG # Uganda ~c427=UGA # Uganda # United Kingdom - bit 278 ~c278=UK # United Kingdom ~c278=GBR # United Kingdom # Ukraine - bit 428 ~c428=UP # Ukraine ~c428=UKR # Ukraine # United States - bit 430 ~c430=US # United States ~c430=USA # United States # Burkina Faso - bit 221 ~c221=UV # Burkina Faso ~c221=BFA # Burkina Faso # Uruguay - bit 429 ~c429=UY # Uruguay ~c429=URY # Uruguay # Uzbekistan - bit 431 ~c431=UZ # Uzbekistan ~c431=UZB # Uzbekistan # Saint Vincent and the Grenadines - bit 433 ~c433=VC # Saint Vincent and the Grenadines ~c433=VCT # Saint Vincent and the Grenadines # Venezuela - bit 434 ~c434=VE # Venezuela ~c434=VEN # Venezuela # British Virgin Islands - bit 435 ~c435=VI # British Virgin Islands ~c435=VGB # British Virgin Islands # Vietnam - bit 437 ~c437=VM # Vietnam ~c437=VNM # Vietnam # Virgin Islands - bit 436 #~c436=VQ # Virgin Islands ~c436=VIR # Virgin Islands # Holy See (Vatican City) - bit 432 ~c432=VT # Holy See (Vatican City) ~c432=VAT # Holy See (Vatican City) # Namibia - bit 358 ~c358=WA # Namibia ~c358=NAM # Namibia # West Bank - bit 383 ~c383=WE # West Bank # Wallis and Futuna - bit 439 ~c439=WF # Wallis and Futuna ~c439=WLF # Wallis and Futuna # Western Sahara - bit 267 ~c267=WI # Western Sahara ~c267=ESH # Western Sahara # Samoa - bit 440 #~c440=WS # Samoa ~c440=WSM # Samoa # Swaziland - bit 409 ~c409=WZ # Swaziland ~c409=SWZ # Swaziland # Yemen - bit 441 #~c441=YM # Yemen ~c441=YEM # Yemen # Zambia - bit 443 ~c443=ZA # Zambia ~c443=ZMB # Zambia # Zimbabwe - bit 444 ~c444=ZI # Zimbabwe ~c444=ZWE # Zimbabwe #UNCLASSIFIED mcstrans/share/examples/nato/setrans.d/rel.conf0100644 0000000 0000000 00000046726 13756670066 020711 0ustar000000000 0000000 #UNCLASSIFIED ModifierGroup=Releasable To Whitespace=- ,/ Join=/ Prefix=REL Prefix=REL TO Prefix=RELEASABLE TO Prefix=RELEASEABLE TO Default=c200.c511 ~c200.c511=EVERBODY ~c200,~c205,~c219,~c223,~c239,~c257,~c258,~c261,~c268,~c269,~c274,~c278,~c288,~c298,~c300,~c308,~c310,~c331,~c332,~c333,~c365,~c366,~c378,~c381,~c387,~c406,~c407,~c423,~c430=NATO # Aruba - bit 201 ~c200,~c201=AA # Aruba ~c200,~c201=ABW # Aruba # Antigua and Barbuda - bit 214 ~c200,~c214=AC # Antigua and Barbuda ~c200,~c214=ATG # Antigua and Barbuda # United Arab Emirates - bit 208 #~c200,~c208=AE # United Arab Emirates ~c200,~c208=ARE # United Arab Emirates # Afghanistan - bit 202 ~c200,~c202=AF # Afghanistan ~c200,~c202=AFG # Afghanistan # Algeria - bit 263 ~c200,~c263=AG # Algeria ~c200,~c263=DZA # Algeria # Azerbaijan - bit 217 ~c200,~c217=AJ # Azerbaijan ~c200,~c217=AZE # Azerbaijan # Albania - bit 205 ~c200,~c205=AL # Albania ~c200,~c205=ALB # Albania # Armenia - bit 210 ~c200,~c210=AM # Armenia ~c200,~c210=ARM # Armenia # Andorra - bit 206 ~c200,~c206=AN # Andorra ~c200,~c206=AND # Andorra # Angola - bit 203 ~c200,~c203=AO # Angola ~c200,~c203=AGO # Angola # American Samoa - bit 211 ~c200,~c211=AQ # American Samoa ~c200,~c211=ASM # American Samoa # Argentina - bit 209 ~c200,~c209=AR # Argentina ~c200,~c209=ARG # Argentina # Australia - bit 215 ~c200,~c215=AUS # Australia ~c200,~c215=AS # Australia # Austria - bit 216 ~c200,~c216=AU # Austria ~c200,~c216=AUT # Austria # Anguilla - bit 204 ~c200,~c204=AV # Anguilla ~c200,~c204=AIA # Anguilla # Antarctica - bit 212 ~c200,~c212=AY # Antarctica ~c200,~c212=ATA # Antarctica # Bahrain - bit 224 ~c200,~c224=BA # Bahrain ~c200,~c224=BHR # Bahrain # Barbados - bit 233 ~c200,~c233=BB # Barbados ~c200,~c233=BRB # Barbados # Botswana - bit 237 ~c200,~c237=BC # Botswana ~c200,~c237=BWA # Botswana # Bermuda - bit 230 ~c200,~c230=BD # Bermuda ~c200,~c230=BMU # Bermuda # Belgium - bit 219 ~c200,~c219=BE # Belgium ~c200,~c219=BEL # Belgium # Bahamas, The - bit 225 ~c200,~c225=BF # Bahamas, The ~c200,~c225=BHS # Bahamas, The # Bangladesh - bit 222 ~c200,~c222=BG # Bangladesh ~c200,~c222=BGD # Bangladesh # Belize - bit 229 ~c200,~c229=BH # Belize ~c200,~c229=BLZ # Belize # Bosnia and Herzegovina - bit 226 ~c200,~c226=BK # Bosnia and Herzegovina ~c200,~c226=BIH # Bosnia and Herzegovina # Bolivia - bit 231 ~c200,~c231=BL # Bolivia ~c200,~c231=BOL # Bolivia # Burma - bit 346 ~c200,~c346=BM # Burma ~c200,~c346=MMR # Burma # Benin - bit 220 ~c200,~c220=BN # Benin ~c200,~c220=BEN # Benin # Belarus - bit 228 ~c200,~c228=BO # Belarus ~c200,~c228=BLR # Belarus # Solomon Islands - bit 397 ~c200,~c397=BP # Solomon Islands ~c200,~c397=SLB # Solomon Islands # Brazil - bit 232 ~c200,~c232=BR # Brazil ~c200,~c232=BRA # Brazil # Bhutan - bit 235 ~c200,~c235=BT # Bhutan ~c200,~c235=BTN # Bhutan # Bulgaria - bit 223 ~c200,~c223=BU # Bulgaria ~c200,~c223=BGR # Bulgaria # Bouvet Island - bit 236 ~c200,~c236=BV # Bouvet Island ~c200,~c236=BVT # Bouvet Island # Brunei - bit 234 ~c200,~c234=BX # Brunei ~c200,~c234=BRN # Brunei # Burundi - bit 218 ~c200,~c218=BY # Burundi ~c200,~c218=BDI # Burundi # Canada - bit 239 ~c200,~c239=CAN # Canada ~c200,~c239=CA # Canada # Cambodia - bit 318 ~c200,~c318=CB # Cambodia ~c200,~c318=KHM # Cambodia # Chad - bit 413 ~c200,~c413=CD # Chad ~c200,~c413=TCD # Chad # Sri Lanka - bit 329 ~c200,~c329=CE # Sri Lanka ~c200,~c329=LKA # Sri Lanka # Congo, Republic of the - bit 247 ~c200,~c247=CF # Congo, Republic of the ~c200,~c247=COG # Congo, Republic of the # Congo, Democratic Republic of the - bit 246 ~c200,~c246=CG # Congo, Democratic Republic of the ~c200,~c246=COD # Congo, Democratic Republic of the # China - bit 243 ~c200,~c243=CH # China ~c200,~c243=CHN # China # Chile - bit 242 ~c200,~c242=CI # Chile ~c200,~c242=CHL # Chile # Cayman Islands - bit 255 ~c200,~c255=CJ # Cayman Islands ~c200,~c255=CYM # Cayman Islands # Cocos (Keeling) Islands - bit 240 part of AUS ~c200,~c240=CK # Cocos (Keeling) Islands ~c200,~c240=CCK # Cocos (Keeling) Islands # Cameroon - bit 245 ~c200,~c245=CM # Cameroon ~c200,~c245=CMR # Cameroon # Comoros - bit 250 ~c200,~c250=CN # Comoros ~c200,~c250=COM # Comoros # Colombia - bit 249 ~c200,~c249=CO # Colombia ~c200,~c249=COL # Colombia # Northern Mariana Islands - bit 349 ~c200,~c349=CQ # Northern Mariana Islands ~c200,~c349=MNP # Northern Mariana Islands # Costa Rica - bit 252 ~c200,~c252=CS # Costa Rica ~c200,~c252=CRI # Costa Rica # Central African Republic - bit 238 ~c200,~c238=CT # Central African Republic ~c200,~c238=CAF # Central African Republic # Cuba - bit 253 ~c200,~c253=CU # Cuba ~c200,~c253=CUB # Cuba # Cape Verde - bit 251 ~c200,~c251=CV # Cape Verde ~c200,~c251=CPV # Cape Verde # Cook Islands - bit 248 ~c200,~c248=CW # Cook Islands ~c200,~c248=COK # Cook Islands # Cyprus - bit 256 ~c200,~c256=CY # Cyprus ~c200,~c256=CYP # Cyprus # Denmark - bit 261 ~c200,~c261=DA # Denmark ~c200,~c261=DNK # Denmark # Djibouti - bit 259 ~c200,~c259=DJ # Djibouti ~c200,~c259=DJI # Djibouti # Dominica - bit 260 ~c200,~c260=DO # Dominica ~c200,~c260=DMA # Dominica # Dominican Republic - bit 262 ~c200,~c262=DR # Dominican Republic ~c200,~c262=DOM # Dominican Republic # Ecuador - bit 264 ~c200,~c264=EC # Ecuador ~c200,~c264=ECU # Ecuador # Egypt - bit 265 ~c200,~c265=EG # Egypt ~c200,~c265=EGY # Egypt # Ireland - bit 305 ~c200,~c305=EI # Ireland ~c200,~c305=IRL # Ireland # Equatorial Guinea - bit 287 ~c200,~c287=EK # Equatorial Guinea ~c200,~c287=GNQ # Equatorial Guinea # Estonia - bit 269 ~c200,~c269=EN # Estonia ~c200,~c269=EST # Estonia # Eritrea - bit 266 ~c200,~c266=ER # Eritrea ~c200,~c266=ERI # Eritrea # El Salvador - bit 399 ~c200,~c399=ES # El Salvador ~c200,~c399=SLV # El Salvador # Ethiopia - bit 270 ~c200,~c270=ET # Ethiopia ~c200,~c270=ETH # Ethiopia # Czech Republic - bit 257 ~c200,~c257=CZE # Czech Republic #~c200,~c257=EZ # Czech Republic # French Guiana - bit 292 ~c200,~c292=FG # French Guiana ~c200,~c292=GUF # French Guiana # Finland - bit 271 ~c200,~c271=FI # Finland ~c200,~c271=FIN # Finland # Fiji - bit 272 ~c200,~c272=FJ # Fiji ~c200,~c272=FJI # Fiji # Falkland Islands (Islas Malvinas) - bit 273 ~c200,~c273=FK # Falkland Islands (Islas Malvinas) ~c200,~c273=FLK # Falkland Islands (Islas Malvinas) # Micronesia, Federated States of - bit 276 ~c200,~c276=FM # Micronesia, Federated States of ~c200,~c276=FSM # Micronesia, Federated States of # Faroe Islands - bit 275 ~c200,~c275=FO # Faroe Islands ~c200,~c275=FRO # Faroe Islands # French Polynesia - bit 384 ~c200,~c384=FP # French Polynesia ~c200,~c384=PYF # French Polynesia # France - bit 274 ~c200,~c274=FR # France ~c200,~c274=FRA # France # French Southern and Antarctic Lands - bit 213 ~c200,~c213=FS # French Southern and Antarctic Lands ~c200,~c213=ATF # French Southern and Antarctic Lands # Gambia, The - bit 285 ~c200,~c285=GA # Gambia, The ~c200,~c285=GMB # Gambia, The # Gabon - bit 277 ~c200,~c277=GB # Gabon ~c200,~c277=GAB # Gabon # Georgia - bit 279 ~c200,~c279=GG # Georgia ~c200,~c279=GEO # Georgia # Ghana - bit 281 ~c200,~c281=GH # Ghana ~c200,~c281=GHA # Ghana # Gibraltar - bit 282 ~c200,~c282=GI # Gibraltar ~c200,~c282=GIB # Gibraltar # Grenada - bit 289 ~c200,~c289=GJ # Grenada ~c200,~c289=GRD # Grenada # Guernsey - bit 280 part of UK ~c200,~c280=GK # Guernsey ~c200,~c280=GGY # Guernsey # Greenland - bit 290 ~c200,~c290=GL # Greenland ~c200,~c290=GRL # Greenland # Germany - bit 258 #~c200,~c258=GM # Germany ~c200,~c258=DEU # Germany # Guadeloupe - bit 284 ~c200,~c284=GP # Guadeloupe ~c200,~c284=GLP # Guadeloupe # Guam - bit 293 ~c200,~c293=GQ # Guam ~c200,~c293=GUM # Guam # Greece - bit 288 ~c200,~c288=GR # Greece ~c200,~c288=GRC # Greece # Guatemala - bit 291 ~c200,~c291=GT # Guatemala ~c200,~c291=GTM # Guatemala # Guinea - bit 283 ~c200,~c283=GV # Guinea ~c200,~c283=GIN # Guinea # Guyana - bit 294 ~c200,~c294=GY # Guyana ~c200,~c294=GUY # Guyana # Gaza Strip - bit 383 #~c200,~c383=GZ # Gaza Strip ~c200,~c383=PSE # Gaza Strip # Haiti - bit 299 ~c200,~c299=HA # Haiti ~c200,~c299=HTI # Haiti # Hong Kong - bit 295 ~c200,~c295=HK # Hong Kong ~c200,~c295=HKG # Hong Kong # Heard Island and McDonald Islands - bit 296 ~c200,~c296=HM # Heard Island and McDonald Islands ~c200,~c296=HMD # Heard Island and McDonald Islands # Honduras - bit 297 ~c200,~c297=HO # Honduras ~c200,~c297=HND # Honduras # Croatia - bit 298 ~c200,~c298=HR # Croatia ~c200,~c298=HRV # Croatia # Hungary - bit 300 ~c200,~c300=HU # Hungary ~c200,~c300=HUN # Hungary # Iceland - bit 308 ~c200,~c308=IC # Iceland ~c200,~c308=ISL # Iceland # Indonesia - bit 301 ~c200,~c301=ID # Indonesia ~c200,~c301=IDN # Indonesia # Isle of Man - bit 302 part of UK ~c200,~c302=IM # Isle of Man ~c200,~c302=IMN # Isle of Man # India - bit 303 ~c200,~c303=IN # India ~c200,~c303=IND # India # British Indian Ocean Territory - bit 304 ~c200,~c304=IO # British Indian Ocean Territory ~c200,~c304=IOT # British Indian Ocean Territory # Iran - bit 306 ~c200,~c306=IR # Iran ~c200,~c306=IRN # Iran # Israel - bit 309 ~c200,~c309=IS # Israel ~c200,~c309=ISR # Israel # Italy - bit 310 ~c200,~c310=IT # Italy ~c200,~c310=ITA # Italy # Cote d'Ivoire - bit 244 ~c200,~c244=IV # Cote d'Ivoire ~c200,~c244=CIV # Cote d'Ivoire # Iraq - bit 307 ~c200,~c307=IZ # Iraq ~c200,~c307=IRQ # Iraq # Japan - bit 314 ~c200,~c314=JA # Japan ~c200,~c314=JPN # Japan # Jersey - bit 312 part of UK ~c200,~c312=JE # Jersey ~c200,~c312=JEY # Jersey # Jamaica - bit 311 ~c200,~c311=JM # Jamaica ~c200,~c311=JAM # Jamaica # Jordan - bit 313 ~c200,~c313=JO # Jordan ~c200,~c313=JOR # Jordan # Kenya - bit 316 ~c200,~c316=KE # Kenya ~c200,~c316=KEN # Kenya # Kyrgyzstan - bit 317 ~c200,~c317=KG # Kyrgyzstan ~c200,~c317=KGZ # Kyrgyzstan # Korea, North - bit 380 ~c200,~c380=KN # Korea, North ~c200,~c380=PRK # Korea, North # Kiribati - bit 319 ~c200,~c319=KR # Kiribati ~c200,~c319=KIR # Kiribati # Korea, South - bit 321 ~c200,~c321=KS # Korea, South ~c200,~c321=ROK # Korea, South # Christmas Island - bit 254 ~c200,~c254=KT # Christmas Island ~c200,~c254=CXR # Christmas Island # Kuwait - bit 322 ~c200,~c322=KU # Kuwait ~c200,~c322=KWT # Kuwait # Kazakhstan - bit 315 ~c200,~c315=KZ # Kazakhstan ~c200,~c315=KAZ # Kazakhstan # Laos - bit 323 ~c200,~c323=LA # Laos ~c200,~c323=LAO # Laos # Lebanon - bit 324 ~c200,~c324=LE # Lebanon ~c200,~c324=LBN # Lebanon # Latvia - bit 333 ~c200,~c333=LG # Latvia ~c200,~c333=LVA # Latvia # Lithuania - bit 331 ~c200,~c331=LH # Lithuania ~c200,~c331=LTU # Lithuania # Liberia - bit 325 ~c200,~c325=LI # Liberia ~c200,~c325=LBR # Liberia # Slovakia - bit 406 ~c200,~c406=LO # Slovakia ~c200,~c406=SVK # Slovakia # Liechtenstein - bit 328 ~c200,~c328=LS # Liechtenstein ~c200,~c328=LIE # Liechtenstein # Lesotho - bit 330 ~c200,~c330=LT # Lesotho ~c200,~c330=LSO # Lesotho # Luxembourg - bit 332 ~c200,~c332=LU # Luxembourg ~c200,~c332=LUX # Luxembourg # Libya - bit 326 ~c200,~c326=LY # Libya ~c200,~c326=LBY # Libya # Madagascar - bit 339 ~c200,~c339=MA # Madagascar ~c200,~c339=MDG # Madagascar # Martinique - bit 353 ~c200,~c353=MB # Martinique ~c200,~c353=MTQ # Martinique # Macau - bit 334 ~c200,~c334=MC # Macau ~c200,~c334=MAC # Macau # Moldova - bit 338 ~c200,~c338=MD # Moldova ~c200,~c338=MDA # Moldova # Mayotte - bit 357 part of FRA ~c200,~c357=MF # Mayotte ~c200,~c357=MYT # Mayotte # Mongolia - bit 348 ~c200,~c348=MG # Mongolia ~c200,~c348=MNG # Mongolia # Montserrat - bit 352 ~c200,~c352=MH # Montserrat ~c200,~c352=MSR # Montserrat # Malawi - bit 355 ~c200,~c355=MI # Malawi ~c200,~c355=MWI # Malawi # Montenegro - bit 347 ~c200,~c347=MJ # Montenegro ~c200,~c347=MNE # Montenegro # Macedonia - bit 343 part of FYR ~c200,~c343=MK # Macedonia ~c200,~c343=MKD # Macedonia # Mali - bit 344 ~c200,~c344=ML # Mali ~c200,~c344=MLI # Mali # Monaco - bit 337 ~c200,~c337=MN # Monaco ~c200,~c337=MCO # Monaco # Morocco - bit 336 ~c200,~c336=MO # Morocco ~c200,~c336=MAR # Morocco # Mauritius - bit 354 ~c200,~c354=MP # Mauritius ~c200,~c354=MUS # Mauritius # Mauritania - bit 351 ~c200,~c351=MR # Mauritania ~c200,~c351=MRT # Mauritania # Malta - bit 345 ~c200,~c345=MT # Malta ~c200,~c345=MLT # Malta # Oman - bit 370 ~c200,~c370=MU # Oman ~c200,~c370=OMN # Oman # Maldives - bit 340 ~c200,~c340=MV # Maldives ~c200,~c340=MDV # Maldives # Mexico - bit 341 ~c200,~c341=MX # Mexico ~c200,~c341=MEX # Mexico # Malaysia - bit 356 ~c200,~c356=MY # Malaysia ~c200,~c356=MYS # Malaysia # Mozambique - bit 350 ~c200,~c350=MZ # Mozambique ~c200,~c350=MOZ # Mozambique # New Caledonia - bit 359 ~c200,~c359=NC # New Caledonia ~c200,~c359=NCL # New Caledonia # Niue - bit 364 ~c200,~c364=NE # Niue ~c200,~c364=NIU # Niue # Norfolk Island - bit 361 ~c200,~c361=NF # Norfolk Island ~c200,~c361=NFK # Norfolk Island # Niger - bit 360 ~c200,~c360=NG # Niger ~c200,~c360=NER # Niger # Vanuatu - bit 438 ~c200,~c438=NH # Vanuatu ~c200,~c438=VUT # Vanuatu # Nigeria - bit 362 ~c200,~c362=NI # Nigeria ~c200,~c362=NGA # Nigeria # Netherlands - bit 365 ~c200,~c365=NL # Netherlands ~c200,~c365=NLD # Netherlands # Norway - bit 366 ~c200,~c366=NO # Norway ~c200,~c366=NOR # Norway # Nepal - bit 367 ~c200,~c367=NP # Nepal ~c200,~c367=NPL # Nepal # Nauru - bit 368 ~c200,~c368=NR # Nauru ~c200,~c368=NRU # Nauru # Suriname - bit 405 ~c200,~c405=NS # Suriname ~c200,~c405=SUR # Suriname # Netherlands Antilles - bit 207 ~c200,~c207=NT # Netherlands Antilles ~c200,~c207=ANT # Netherlands Antilles # Nicaragua - bit 363 ~c200,~c363=NU # Nicaragua ~c200,~c363=NIC # Nicaragua # New Zealand - bit 369 ~c200,~c369=NZ # New Zealand ~c200,~c369=NZL # New Zealand # Paraguay - bit 382 ~c200,~c382=PA # Paraguay ~c200,~c382=PRY # Paraguay # Pitcairn Islands - bit 373 ~c200,~c373=PC # Pitcairn Islands ~c200,~c373=PCN # Pitcairn Islands # Peru - bit 374 ~c200,~c374=PE # Peru ~c200,~c374=PER # Peru # Pakistan - bit 371 ~c200,~c371=PK # Pakistan ~c200,~c371=PAK # Pakistan # Poland - bit 378 ~c200,~c378=PL # Poland ~c200,~c378=POL # Poland # Panama - bit 372 ~c200,~c372=PM # Panama ~c200,~c372=PAN # Panama # Portugal - bit 381 ~c200,~c381=PO # Portugal ~c200,~c381=PRT # Portugal # Papua New Guinea - bit 377 ~c200,~c377=PP # Papua New Guinea ~c200,~c377=PNG # Papua New Guinea # Palau - bit 376 #~c200,~c376=PS # Palau ~c200,~c376=PLW # Palau # Guinea-Bissau - bit 286 ~c200,~c286=PU # Guinea-Bissau ~c200,~c286=GNB # Guinea-Bissau # Qatar - bit 385 ~c200,~c385=QA # Qatar ~c200,~c385=QAT # Qatar # Serbia - bit 403 #~c200,~c403=RB # Serbia ~c200,~c403=SRB # Serbia # Reunion - bit 386 ~c200,~c386=RE # Reunion ~c200,~c386=REU # Reunion # Marshall Islands - bit 342 ~c200,~c342=RM # Marshall Islands ~c200,~c342=MHL # Marshall Islands # Saint Martin - bit 335 ~c200,~c335=RN # Saint Martin ~c200,~c335=MAF # Saint Martin # Romania - bit 387 ~c200,~c387=RO # Romania ~c200,~c387=ROU # Romania # Philippines - bit 375 ~c200,~c375=RP # Philippines ~c200,~c375=PHL # Philippines # Puerto Rico - bit 379 ~c200,~c379=RQ # Puerto Rico ~c200,~c379=PRI # Puerto Rico # Russia - bit 388 #~c200,~c388=RS # Russia ~c200,~c388=RUS # Russia # Rwanda - bit 389 ~c200,~c389=RW # Rwanda ~c200,~c389=RWA # Rwanda # Saudi Arabia - bit 390 ~c200,~c390=SA # Saudi Arabia ~c200,~c390=SAU # Saudi Arabia # Saint Pierre and Miquelon - bit 402 ~c200,~c402=SB # Saint Pierre and Miquelon ~c200,~c402=SPM # Saint Pierre and Miquelon # Saint Kitts and Nevis - bit 320 ~c200,~c320=SC # Saint Kitts and Nevis ~c200,~c320=KNA # Saint Kitts and Nevis # Seychelles - bit 410 ~c200,~c410=SE # Seychelles ~c200,~c410=SYC # Seychelles # South Africa - bit 442 ~c200,~c442=SF # South Africa ~c200,~c442=ZAF # South Africa # Senegal - bit 392 ~c200,~c392=SG # Senegal ~c200,~c392=SEN # Senegal # Saint Helena - bit 395 ~c200,~c395=SH # Saint Helena ~c200,~c395=SHN # Saint Helena # Slovenia - bit 407 #~c200,~c407=SI # Slovenia ~c200,~c407=SVN # Slovenia # Sierra Leone - bit 398 ~c200,~c398=SL # Sierra Leone ~c200,~c398=SLE # Sierra Leone # San Marino - bit 400 ~c200,~c400=SM # San Marino ~c200,~c400=SMR # San Marino # Singapore - bit 393 ~c200,~c393=SN # Singapore ~c200,~c393=SGP # Singapore # Somalia - bit 401 ~c200,~c401=SO # Somalia ~c200,~c401=SOM # Somalia # Spain - bit 268 #~c200,~c268=SP # Spain ~c200,~c268=ESP # Spain # Saint Lucia - bit 327 ~c200,~c327=ST # Saint Lucia ~c200,~c327=LCA # Saint Lucia # Sudan - bit 391 ~c200,~c391=SU # Sudan ~c200,~c391=SDN # Sudan # Svalbard - bit 396 #~c200,~c396=SV # Svalbard ~c200,~c396=SJM # Svalbard # Sweden - bit 408 ~c200,~c408=SW # Sweden ~c200,~c408=SWE # Sweden # South Georgia and the Islands - bit 394 ~c200,~c394=SX # South Georgia and the Islands ~c200,~c394=SGS # South Georgia and the Islands # Syria - bit 411 ~c200,~c411=SY # Syria ~c200,~c411=SYR # Syria # Switzerland - bit 241 ~c200,~c241=SZ # Switzerland ~c200,~c241=CHE # Switzerland # Saint Barthelemy - bit 227 ~c200,~c227=TB # Saint Barthelemy ~c200,~c227=BLM # Saint Barthelemy # Trinidad and Tobago - bit 421 ~c200,~c421=TD # Trinidad and Tobago ~c200,~c421=TTO # Trinidad and Tobago # Thailand - bit 415 ~c200,~c415=TH # Thailand ~c200,~c415=THA # Thailand # Tajikistan - bit 416 ~c200,~c416=TI # Tajikistan ~c200,~c416=TJK # Tajikistan # Turks and Caicos Islands - bit 412 ~c200,~c412=TK # Turks and Caicos Islands ~c200,~c412=TCA # Turks and Caicos Islands # Togo - bit 414 ~c200,~c414=TGO # Togo # Tokelau - bit 417 ~c200,~c417=TL # Tokelau ~c200,~c417=TKL # Tokelau # Tonga - bit 420 ~c200,~c420=TN # Tonga ~c200,~c420=TON # Tonga # Sao Tome and Principe - bit 404 ~c200,~c404=TP # Sao Tome and Principe ~c200,~c404=STP # Sao Tome and Principe # Tunisia - bit 422 ~c200,~c422=TS # Tunisia ~c200,~c422=TUN # Tunisia # Timor-Leste - bit 419 ~c200,~c419=TT # Timor-Leste ~c200,~c419=TLS # Timor-Leste # Turkey - bit 423 ~c200,~c423=TU # Turkey ~c200,~c423=TUR # Turkey # Tuvalu - bit 424 ~c200,~c424=TV # Tuvalu ~c200,~c424=TUV # Tuvalu # Taiwan - bit 425 ~c200,~c425=TW # Taiwan ~c200,~c425=TWN # Taiwan # Turkmenistan - bit 418 ~c200,~c418=TX # Turkmenistan ~c200,~c418=TKM # Turkmenistan # Tanzania - bit 426 ~c200,~c426=TZ # Tanzania ~c200,~c426=TZA # Tanzania # Uganda - bit 427 ~c200,~c427=UG # Uganda ~c200,~c427=UGA # Uganda # United Kingdom - bit 278 ~c200,~c278=UK # United Kingdom ~c200,~c278=GBR # United Kingdom # Ukraine - bit 428 ~c200,~c428=UP # Ukraine ~c200,~c428=UKR # Ukraine # United States - bit 430 ~c200,~c430=US # United States ~c200,~c430=USA # United States # Burkina Faso - bit 221 ~c200,~c221=UV # Burkina Faso ~c200,~c221=BFA # Burkina Faso # Uruguay - bit 429 ~c200,~c429=UY # Uruguay ~c200,~c429=URY # Uruguay # Uzbekistan - bit 431 ~c200,~c431=UZ # Uzbekistan ~c200,~c431=UZB # Uzbekistan # Saint Vincent and the Grenadines - bit 433 ~c200,~c433=VC # Saint Vincent and the Grenadines ~c200,~c433=VCT # Saint Vincent and the Grenadines # Venezuela - bit 434 ~c200,~c434=VE # Venezuela ~c200,~c434=VEN # Venezuela # British Virgin Islands - bit 435 ~c200,~c435=VI # British Virgin Islands ~c200,~c435=VGB # British Virgin Islands # Vietnam - bit 437 ~c200,~c437=VM # Vietnam ~c200,~c437=VNM # Vietnam # Virgin Islands - bit 436 #~c200,~c436=VQ # Virgin Islands ~c200,~c436=VIR # Virgin Islands # Holy See (Vatican City) - bit 432 ~c200,~c432=VT # Holy See (Vatican City) ~c200,~c432=VAT # Holy See (Vatican City) # Namibia - bit 358 ~c200,~c358=WA # Namibia ~c200,~c358=NAM # Namibia # West Bank - bit 383 ~c200,~c383=WE # West Bank # Wallis and Futuna - bit 439 ~c200,~c439=WF # Wallis and Futuna ~c200,~c439=WLF # Wallis and Futuna # Western Sahara - bit 267 ~c200,~c267=WI # Western Sahara ~c200,~c267=ESH # Western Sahara # Samoa - bit 440 #~c200,~c440=WS # Samoa ~c200,~c440=WSM # Samoa # Swaziland - bit 409 ~c200,~c409=WZ # Swaziland ~c200,~c409=SWZ # Swaziland # Yemen - bit 441 #~c200,~c441=YM # Yemen ~c200,~c441=YEM # Yemen # Zambia - bit 443 ~c200,~c443=ZA # Zambia ~c200,~c443=ZMB # Zambia # Zimbabwe - bit 444 ~c200,~c444=ZI # Zimbabwe ~c200,~c444=ZWE # Zimbabwe #UNCLASSIFIEDmcstrans/share/examples/non-mls-color/0040755 0000000 0000000 00000000000 13756670066 017101 5ustar000000000 0000000 mcstrans/share/examples/non-mls-color/README0100644 0000000 0000000 00000000246 13756670066 017760 0ustar000000000 0000000 Non-MLS color example To use: cp secolor.conf /etc/selinux/mls/ run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlscolor-test non-mls.color mcstrans/share/examples/non-mls-color/non-mls.color0100644 0000000 0000000 00000000450 13756670066 021520 0ustar000000000 0000000 system_u:system_r:inetd_t:SystemLow=#000000 #008000 #ffffff #000000 #d2b48c #ffa500 #000000 #008000 system_u:system_r:inetd_t:SystemHigh=#000000 #008000 #ffffff #000000 #d2b48c #ffa500 #000000 #008000 user_u:user_r:user_t:SystemLow=#000000 #008000 #ffffff #000000 #d2b48c #ffa500 #000000 #008000 mcstrans/share/examples/non-mls-color/secolor.conf0100644 0000000 0000000 00000000355 13756670066 021416 0ustar000000000 0000000 color black = #000000 color green = #008000 color yellow = #ffff00 color blue = #0000ff color white = #ffffff color red = #ff0000 color orange = #ffa500 color tan = #D2B48C user * = black green role * = white black type * = tan orange mcstrans/share/examples/pipes/0040755 0000000 0000000 00000000000 13756670066 015522 5ustar000000000 0000000 mcstrans/share/examples/pipes/pipes.test0100644 0000000 0000000 00000000610 13756670066 017535 0ustar000000000 0000000 Restricted Handle Via Iron Pipes Only==s2:c102,c200.c511 Restricted Handle Via Copper Pipes Only==s2:c103,c200.c511 Restricted Handle Via Plastic Pipes Only==s2:c101,c200.c511 Restricted Handle Via Galvanized Pipes Only==s2:c104,c200.c511 Restricted Handle Via Plastic,Iron,Copper Pipes Only==s2:c101.c103,c200.c511 Restricted Handle Via Iron,Plastic,Copper Pipes Only=s2:c101.c103,c200.c511 mcstrans/share/examples/pipes/setrans.conf0100644 0000000 0000000 00000000525 13756670066 020047 0ustar000000000 0000000 Domain=PipesTest s0=SystemLow s15:c0.c1023=SystemHigh s0-s15:c0.c1023=SystemLow-SystemHigh Base=Sensitivity Levels s1=Unclassified s1=U s2:c200.c511=Restricted s2:c200.c511=R s3:c200.c511=Confidential s3:c200.c511=C s4:c200.c511=Secret s4:c200.c511=S s5:c200.c511=Top Secret s5:c200.c511=TS Include=/etc/selinux/mls/setrans.d/pipes.conf mcstrans/share/examples/pipes/setrans.d/0040755 0000000 0000000 00000000000 13756670066 017423 5ustar000000000 0000000 mcstrans/share/examples/pipes/setrans.d/pipes.conf0100644 0000000 0000000 00000000217 13756670066 021407 0ustar000000000 0000000 ModifierGroup=Pipes Prefix=Handle Via Suffix=Pipes Only Suffix=Pipes Whitespace=, Join=, c101=Plastic c102=Iron c103=Copper c104=Galvanized mcstrans/share/examples/urcsts-via-include/0040755 0000000 0000000 00000000000 13756670066 020123 5ustar000000000 0000000 mcstrans/share/examples/urcsts-via-include/README0100644 0000000 0000000 00000000545 13756670066 021004 0ustar000000000 0000000 Simple handling of UNCLASSIFIED RESTRICTED CONFIDENTIAL SECRET TOP SECRET via include files To use: cp -L setrans.conf /etc/selinux/mls/ cp -L secolor.conf /etc/selinux/mls/ rm -f /etc/selinux/mls/setrans.d/* cp setrans.d/* /etc/selinux/mls/setrans.d run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlstrans-test urcsts.test mcstrans/share/examples/urcsts-via-include/secolor.conf0100644 0000000 0000000 00000000737 13756670066 022444 0ustar000000000 0000000 color black = #000000 color green = #008000 color yellow = #ffff00 color blue = #0000ff color white = #ffffff color red = #ff0000 color orange = #ffa500 color tan = #D2B48C user * = black black role * = black black type * = black black range s0-s0:c0.c1023 = black green range s1-s1:c0.c1023 = black green range s3-s3:c0.c1023 = black tan range s5-s5:c0.c1023 = white blue range s7-s7:c0.c1023 = black red range s9-s9:c0.c1023 = black orange range s15:c0.c1023 = black yellow mcstrans/share/examples/urcsts-via-include/setrans.conf0100644 0000000 0000000 00000000745 13756670066 022454 0ustar000000000 0000000 # # Multi-Level Security translation table for SELinux # # Uncomment the following to disable translation libary # disable=1 # # Objects can be labeled with one of 16 levels and be categorized with 0-1023 # categories defined by the admin. # Objects can be in more than one category at a time. # Users can modify this table to translate the MLS labels for different purpose. # # Demonstrate Include by moving everthing to an include file # Include=/etc/selinux/mls/setrans.d/*.conf mcstrans/share/examples/urcsts-via-include/setrans.d/0040755 0000000 0000000 00000000000 13756670066 022024 5ustar000000000 0000000 mcstrans/share/examples/urcsts-via-include/setrans.d/c.conf0100644 0000000 0000000 00000000120 13756670066 023103 0ustar000000000 0000000 # UNCLASSIFIED s5=CONFIDENTIAL s5=C O N F I D E N T I A L s5=C # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/setrans.d/r.conf0100644 0000000 0000000 00000000112 13756670066 023123 0ustar000000000 0000000 # UNCLASSIFIED s3=RESTRICTED s3=R E S T R I C T E D s3=R # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/setrans.d/s.conf0100644 0000000 0000000 00000000076 13756670066 023135 0ustar000000000 0000000 # UNCLASSIFIED s7=SECRET s7=S E C R E T s7=S # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/setrans.d/system.conf0100644 0000000 0000000 00000000105 13756670066 024210 0ustar000000000 0000000 # UNCLASSIFIED s0=SystemLow s15:c0.c1023=SystemHigh # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/setrans.d/ts.conf0100644 0000000 0000000 00000000137 13756670066 023317 0ustar000000000 0000000 # UNCLASSIFIED s9=TOP SECRET s9=T O P S E C R E T s9=T O P S E C R E T s9=TS # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/setrans.d/u.conf0100644 0000000 0000000 00000000077 13756670066 023140 0ustar000000000 0000000 # UNCLASSIFIED s1=UNCLASSIFIED s1=UNCLAS s1=U # UNCLASSIFIED mcstrans/share/examples/urcsts-via-include/urcsts.color0100644 0000000 0000000 00000003634 13756670066 022511 0ustar000000000 0000000 system_u:system_r:inetd_t:SystemLow=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s0=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s0:c1=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:UNCLASSIFIED=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s1=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s1:c2=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:RESTRICTED=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:s3=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:s3:c3=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:CONFIDENTIAL=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:s5=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:s5:c0.c5=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:SECRET=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:s7=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:s7:c200.c300=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:TOP SECRET=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s9=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s9:c1023=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s15=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffff00 system_u:system_r:inetd_t:SystemHigh=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffff00 mcstrans/share/examples/urcsts-via-include/urcsts.test0100644 0000000 0000000 00000000445 13756670066 022347 0ustar000000000 0000000 # UNCLASSIFIED SystemLow=s0 SystemHigh=s15:c0.c1023 UNCLASSIFIED==s1 UNCLAS=s1 U=s1 RESTRICTED==s3 R E S T R I C T E D=s3 R=s3 CONFIDENTIAL==s5 C O N F I D E N T I A L=s5 C=s5 SECRET==s7 S E C R E T=s7 S=s7 TOP SECRET==s9 T O P S E C R E T=s9 T O P S E C R E T=s9 TS=s9 # UNCLASSIFIED mcstrans/share/examples/urcsts/0040755 0000000 0000000 00000000000 13756670066 015725 5ustar000000000 0000000 mcstrans/share/examples/urcsts/README0100644 0000000 0000000 00000000477 13756670066 016612 0ustar000000000 0000000 Simple handling of UNCLASSIFIED RESTRICTED CONFIDENTIAL SECRET TOP SECRET To use: cp setrans.conf /etc/selinux/mls/setrans.conf cp secolor.conf /etc/selinux/mls/ run_init /etc/init.d/mcstrans restart To test: /usr/share/mcstrans/util/mlstrans-test urcsts.test /usr/share/mcstrans/util/mlscolor-test urcsts.color mcstrans/share/examples/urcsts/secolor.conf0100644 0000000 0000000 00000000737 13756670066 020246 0ustar000000000 0000000 color black = #000000 color green = #008000 color yellow = #ffff00 color blue = #0000ff color white = #ffffff color red = #ff0000 color orange = #ffa500 color tan = #D2B48C user * = black black role * = black black type * = black black range s0-s0:c0.c1023 = black green range s1-s1:c0.c1023 = black green range s3-s3:c0.c1023 = black tan range s5-s5:c0.c1023 = white blue range s7-s7:c0.c1023 = black red range s9-s9:c0.c1023 = black orange range s15:c0.c1023 = black yellow mcstrans/share/examples/urcsts/setrans.conf0100644 0000000 0000000 00000000440 13756670066 020246 0ustar000000000 0000000 # UNCLASSIFIED s0=SystemLow s15:c0.c1023=SystemHigh s1=UNCLASSIFIED s1=UNCLAS s1=U s3=RESTRICTED s3=R E S T R I C T E D s3=R s5=CONFIDENTIAL s5=C O N F I D E N T I A L s5=C s7=SECRET s7=S E C R E T s7=S s9=TOP SECRET s9=T O P S E C R E T s9=T O P S E C R E T s9=TS # UNCLASSIFIED mcstrans/share/examples/urcsts/urcsts.color0100644 0000000 0000000 00000003634 13756670066 020313 0ustar000000000 0000000 system_u:system_r:inetd_t:SystemLow=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s0=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s0:c1=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:UNCLASSIFIED=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s1=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:s1:c2=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #008000 system_u:system_r:inetd_t:RESTRICTED=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:s3=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:s3:c3=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #d2b48c system_u:system_r:inetd_t:CONFIDENTIAL=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:s5=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:s5:c0.c5=#000000 #000000 #000000 #000000 #000000 #000000 #ffffff #0000ff system_u:system_r:inetd_t:SECRET=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:s7=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:s7:c200.c300=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ff0000 system_u:system_r:inetd_t:TOP SECRET=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s9=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s9:c1023=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffa500 system_u:system_r:inetd_t:s15=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffff00 system_u:system_r:inetd_t:SystemHigh=#000000 #000000 #000000 #000000 #000000 #000000 #000000 #ffff00 mcstrans/share/examples/urcsts/urcsts.test0100644 0000000 0000000 00000000445 13756670066 020151 0ustar000000000 0000000 # UNCLASSIFIED SystemLow=s0 SystemHigh=s15:c0.c1023 UNCLASSIFIED==s1 UNCLAS=s1 U=s1 RESTRICTED==s3 R E S T R I C T E D=s3 R=s3 CONFIDENTIAL==s5 C O N F I D E N T I A L=s5 C=s5 SECRET==s7 S E C R E T=s7 S=s7 TOP SECRET==s9 T O P S E C R E T=s9 T O P S E C R E T=s9 TS=s9 # UNCLASSIFIED mcstrans/share/util/0040755 0000000 0000000 00000000000 13756670066 013541 5ustar000000000 0000000 mcstrans/share/util/mlscolor-test0100644 0000000 0000000 00000002131 13756670066 016265 0ustar000000000 0000000 #!/usr/bin/python3 -E import sys import selinux verbose = 0 errors = 0 if len(sys.argv) > 1 and sys.argv[1] == "-v": verbose = 1 for arg in sys.argv[1:]: f = open(arg, 'r') for line in f: if line.startswith('#'): continue if not line.strip(): continue line = line.rstrip('\n') # print line context, expected = line.split("=") rc, raw = selinux.selinux_trans_to_raw_context(context) if rc < 0: print("Unable to get raw context of '%s'" % (context)) errors += 1 continue rc, colors = selinux.selinux_raw_context_to_color(raw) if rc < 0: print("Unable to get colors for '%s'" % (context)) errors += 1 continue colors = colors.rstrip() if colors != expected: print("For '%s' got\n\t'%s' expected\n\t'%s'" % (context, colors, expected)) errors += 1 continue f.close() s = "s" if errors == 1: s = "" print("mlscolor-test done with %d error%s" % (errors, s)) sys.exit(errors) mcstrans/share/util/mlstrans-test0100644 0000000 0000000 00000002547 13756670066 016311 0ustar000000000 0000000 #!/usr/bin/python3 -E import sys import selinux verbose = 0 errors = 0 def untrans(trans, val): global errors, verbose (rc, raw) = selinux.selinux_trans_to_raw_context(trans) if raw != val: print("untrans: '%s' -> '%s' != '%s' FAILED" % (trans, raw, val)) errors += 1 else: if verbose: print("untrans: %s -> %s != %s SUCCESS" % (trans, raw, val)) def trans(raw, val): global errors, verbose (rc, trans) = selinux.selinux_raw_to_trans_context(raw) if trans != val: print("trans: '%s' -> '%s' != '%s' FAILED" % (raw, trans, val)) errors += 1 else: if verbose: print("trans: %s -> %s != %s SUCCESS" % (raw, trans, val)) if len(sys.argv) > 1 and sys.argv[1] == "-v": verbose = 1 for arg in sys.argv[1:]: f = open(arg, 'r') for line in f: if line.startswith('#'): continue if not line.strip(): continue line = line.rstrip('\n') if line.find("==") != -1: t, r = line.split("==") untrans("a:b:c:" + t, "a:b:c:" + r) trans("a:b:c:" + r, "a:b:c:" + t) else: t, r = line.split("=") untrans("a:b:c:" + t, "a:b:c:" + r) f.close() s = "s" if errors == 1: s = "" print("mlstrans-test done with %d error%s" % (errors, s)) sys.exit(errors) mcstrans/share/util/try-all0100644 0000000 0000000 00000003341 13756670066 015046 0ustar000000000 0000000 #!/bin/bash shopt -s nullglob fail() { echo $1 exit 1 } [ `id -u` = 0 ] || fail "must run as root" for d in /usr/share/mcstrans/examples/*; do echo $d rm -rf /etc/selinux/mls/setrans.conf.bak /etc/selinux/mls/secolor.conf.bak /etc/selinux/mls/setrans.d.bak [ $? -eq 0 ] || fail "preclean failed" if [ -e $d/setrans.conf ]; then mv /etc/selinux/mls/setrans.conf /etc/selinux/mls/setrans.conf.bak [ $? -eq 0 ] || fail "setrans.conf backup failed" fi if [ -e /etc/selinux/mls/secolor.conf ]; then mv /etc/selinux/mls/secolor.conf /etc/selinux/mls/secolor.conf.bak [ $? -eq 0 ] || fail "secolor.conf backup failed" fi mv /etc/selinux/mls/setrans.d /etc/selinux/mls/setrans.d.bak [ $? -eq 0 ] || fail "setrans.d backup failed" if [ -e $d/setrans.conf ]; then cp -L $d/setrans.conf /etc/selinux/mls/setrans.conf fi if [ -e $d/secolor.conf ]; then cp -L $d/secolor.conf /etc/selinux/mls fi if [ -d $d/setrans.d ]; then cp -Lr $d/setrans.d /etc/selinux/mls fi runcon `cat /etc/selinux/mls/contexts/initrc_context` /etc/init.d/mcstrans restart for t in $d/*.test; do /usr/share/mcstrans/util/mlstrans-test $t done for c in $d/*.color; do /usr/share/mcstrans/util/mlscolor-test $c done if [ -e /etc/selinux/mls/setrans.conf.bak ]; then mv /etc/selinux/mls/setrans.conf.bak /etc/selinux/mls/setrans.conf fi if [ -e /etc/selinux/mls/secolor.conf.bak ]; then mv /etc/selinux/mls/secolor.conf.bak /etc/selinux/mls/secolor.conf fi rm -rf /etc/selinux/mls/setrans.d mv /etc/selinux/mls/setrans.d.bak /etc/selinux/mls/setrans.d restorecon -rv /etc/selinux/mls/setrans.conf /etc/selinux/mls/setrans.d >/dev/null runcon `cat /etc/selinux/mls/contexts/initrc_context` /etc/init.d/mcstrans restart done exit 0 mcstrans/src/0040755 0000000 0000000 00000000000 13756670066 012251 5ustar000000000 0000000 mcstrans/src/.gitignore0100644 0000000 0000000 00000000012 13756670066 014227 0ustar000000000 0000000 mcstransd mcstrans/src/Makefile0100644 0000000 0000000 00000002443 13756670066 013711 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr SBINDIR ?= /sbin INITDIR ?= /etc/rc.d/init.d SYSTEMDDIR ?= $(PREFIX)/lib/systemd # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there # is no need to define a value for LDLIBS_LIBSEPOLA ifeq ($(LIBSEPOLA),) LDLIBS_LIBSEPOLA := -l:libsepol.a endif PROG_SRC=mcstrans.c mcscolor.c mcstransd.c mls_level.c PROG_OBJS= $(patsubst %.c,%.o,$(PROG_SRC)) PROG=mcstransd INITSCRIPT=mcstrans CFLAGS ?= -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute all: $(PROG) $(PROG): $(PROG_OBJS) $(LIBSEPOLA) $(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap -lpcre $(LDLIBS_LIBSEPOLA) %.o: %.c $(CC) $(CFLAGS) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -fPIE -c -o $@ $< install: all test -d $(DESTDIR)$(SBINDIR) || install -m 755 -d $(DESTDIR)$(SBINDIR) install -m 755 $(PROG) $(DESTDIR)$(SBINDIR) test -d $(DESTDIR)$(INITDIR) || install -m 755 -d $(DESTDIR)$(INITDIR) install -m 755 $(INITSCRIPT).init $(DESTDIR)$(INITDIR)/$(INITSCRIPT) test -d $(DESTDIR)$(SYSTEMDDIR)/system || install -m 755 -d $(DESTDIR)$(SYSTEMDDIR)/system install -m 644 mcstrans.service $(DESTDIR)$(SYSTEMDDIR)/system/ clean: -rm -f $(OBJS) $(LOBJS) $(TARGET) $(PROG) $(PROG_OBJS) *~ \#* mcstrans/src/README0100644 0000000 0000000 00000000233 13756670066 013124 0ustar000000000 0000000 To rebuild with debugging support: make clean && env CFLAGS="-Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -DDEBUG -g" LDFLAGS="-g" make mcstrans/src/mcscolor.c0100644 0000000 0000000 00000015615 13756670066 014243 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mcstrans.h" /* Define data structures */ typedef struct secolor { uint32_t fg; uint32_t bg; } secolor_t; typedef struct semnemonic { char *name; uint32_t color; struct semnemonic *next; } semnemonic_t; typedef struct setab { char *pattern; secolor_t color; struct setab *next; } setab_t; #define COLOR_USER 0 #define COLOR_ROLE 1 #define COLOR_TYPE 2 #define COLOR_RANGE 3 #define N_COLOR 4 #define AUX_RULE_COLOR "color" static const char *rules[] = { "user", "role", "type", "range" }; static setab_t *clist[N_COLOR]; static setab_t *cend[N_COLOR]; static semnemonic_t *mnemonics; static security_context_t my_context; void finish_context_colors(void) { setab_t *cur, *next; semnemonic_t *ptr; unsigned i; for (i = 0; i < N_COLOR; i++) { cur = clist[i]; while(cur) { next = cur->next; free(cur->pattern); free(cur); cur = next; } clist[i] = cend[i] = NULL; } ptr = mnemonics; while (ptr) { mnemonics = ptr->next; free(ptr->name); free(ptr); ptr = mnemonics; } mnemonics = NULL; freecon(my_context); my_context = NULL; } static int check_dominance(const char *pattern, const char *raw) { security_context_t ctx; context_t con; struct av_decision avd; int rc = -1; context_t my_tmp; const char *raw_range; security_class_t context_class = string_to_security_class("context"); access_vector_t context_contains_perm = string_to_av_perm(context_class, "contains"); con = context_new(raw); if (!con) return -1; raw_range = context_range_get(con); my_tmp = context_new(my_context); if (!my_tmp) { context_free(con); return -1; } ctx = NULL; if (context_range_set(my_tmp, pattern)) goto out; ctx = strdup(context_str(my_tmp)); if (!ctx) goto out; if (context_range_set(my_tmp, raw_range)) goto out; raw = context_str(my_tmp); if (!raw) goto out; rc = security_compute_av_raw(ctx, (security_context_t)raw, context_class, context_contains_perm, &avd); if (rc) goto out; rc = (context_contains_perm & avd.allowed) != context_contains_perm; out: free(ctx); context_free(my_tmp); context_free(con); return rc; } static const secolor_t *find_color(int idx, const char *component, const char *raw) { setab_t *ptr = clist[idx]; if (idx == COLOR_RANGE) { if (!raw) { return NULL; } } else if (!component) { return NULL; } while (ptr) { if (fnmatch(ptr->pattern, component, 0) == 0) { if (idx == COLOR_RANGE) { if (check_dominance(ptr->pattern, raw) == 0) return &ptr->color; } else return &ptr->color; } ptr = ptr->next; } return NULL; } static int add_secolor(int idx, char *pattern, uint32_t fg, uint32_t bg) { setab_t *cptr; cptr = calloc(1, sizeof(setab_t)); if (!cptr) return -1; cptr->pattern = strdup(pattern); if (!cptr->pattern) { free(cptr); return -1; } cptr->color.fg = fg & 0xffffff; cptr->color.bg = bg & 0xffffff; if (cend[idx]) { cend[idx]->next = cptr; cend[idx] = cptr; } else { clist[idx] = cptr; cend[idx] = cptr; } return 0; } static int find_mnemonic(const char *name, uint32_t *retval) { semnemonic_t *ptr; if (*name == '#') return sscanf(name, "#%x", retval) == 1 ? 0 : -1; ptr = mnemonics; while (ptr) { if (!strcmp(ptr->name, name)) { *retval = ptr->color; return 0; } ptr = ptr->next; } return -1; } static int add_mnemonic(const char *name, uint32_t color) { semnemonic_t *ptr = malloc(sizeof(semnemonic_t)); if (!ptr) return -1; ptr->color = color; ptr->name = strdup(name); if (!ptr->name) { free(ptr); return -1; } ptr->next = mnemonics; mnemonics = ptr; return 0; } /* Process line from color file. May modify the data pointed to by the buffer paremeter */ static int process_color(char *buffer, int line) { char rule[10], pat[256], f[256], b[256]; uint32_t i, fg, bg; int ret; while(isspace(*buffer)) buffer++; if(buffer[0] == '#' || buffer[0] == '\0') return 0; ret = sscanf(buffer, "%8s %255s = %255s %255s", rule, pat, f, b); if (ret == 4) { if (find_mnemonic(f, &fg) == 0 && find_mnemonic(b, &bg) == 0) for (i = 0; i < N_COLOR; i++) if (!strcmp(rule, rules[i])) return add_secolor(i, pat, fg, bg); } else if (ret == 3) { if (!strcmp(rule, AUX_RULE_COLOR)) { if (sscanf(f, "#%x", &fg) == 1) return add_mnemonic(pat, fg); } } syslog(LOG_WARNING, "Line %d of secolors file is invalid.", line); return 0; } /* Read in color file. */ int init_colors(void) { FILE *cfg = NULL; size_t size = 0; char *buffer = NULL; int line = 0; getcon(&my_context); cfg = fopen(selinux_colors_path(), "r"); if (!cfg) return 1; __fsetlocking(cfg, FSETLOCKING_BYCALLER); while (getline(&buffer, &size, cfg) > 0) { if( process_color(buffer, ++line) < 0 ) break; } free(buffer); fclose(cfg); return 0; } static const unsigned precedence[N_COLOR][N_COLOR - 1] = { { COLOR_ROLE, COLOR_TYPE, COLOR_RANGE }, { COLOR_USER, COLOR_TYPE, COLOR_RANGE }, { COLOR_USER, COLOR_ROLE, COLOR_RANGE }, { COLOR_USER, COLOR_ROLE, COLOR_TYPE }, }; static const secolor_t default_color = { 0x000000, 0xffffff }; static int parse_components(context_t con, char **components) { components[COLOR_USER] = (char *)context_user_get(con); components[COLOR_ROLE] = (char *)context_role_get(con); components[COLOR_TYPE] = (char *)context_type_get(con); components[COLOR_RANGE] = (char *)context_range_get(con); return 0; } /* Look up colors. */ int raw_color(const security_context_t raw, char **color_str) { #define CHARS_PER_COLOR 16 context_t con; uint32_t i, j, mask = 0; const secolor_t *items[N_COLOR]; char *result, *components[N_COLOR]; char buf[CHARS_PER_COLOR + 1]; size_t result_size = (N_COLOR * CHARS_PER_COLOR) + 1; int rc = -1; if (!color_str || *color_str) { return -1; } /* parse context and allocate memory */ con = context_new(raw); if (!con) return -1; if (parse_components(con, components) < 0) goto out; result = malloc(result_size); if (!result) goto out; result[0] = '\0'; /* find colors for which we have a match */ for (i = 0; i < N_COLOR; i++) { items[i] = find_color(i, components[i], raw); if (items[i]) mask |= (1 << i); } if (mask == 0) { items[0] = &default_color; mask = 1; } /* propagate colors according to the precedence rules */ for (i = 0; i < N_COLOR; i++) if (!(mask & (1 << i))) for (j = 0; j < N_COLOR - 1; j++) if (mask & (1 << precedence[i][j])) { items[i] = items[precedence[i][j]]; break; } /* print results into a big long string */ for (i = 0; i < N_COLOR; i++) { snprintf(buf, sizeof(buf), "#%06x #%06x ", items[i]->fg, items[i]->bg); strncat(result, buf, result_size-1); } *color_str = result; rc = 0; out: context_free(con); return rc; } mcstrans/src/mcstrans.c0100644 0000000 0000000 00000121322 13756670066 014245 0ustar000000000 0000000 /* Copyright (c) 2008-2009 Nall Design Works Copyright 2006 Trusted Computer Solutions, Inc. */ /* Exported Interface int init_translations(void); void finish_context_translations(void); int trans_context(const security_context_t, security_context_t *); int untrans_context(const security_context_t, security_context_t *); */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mls_level.h" #include "mcstrans.h" #define N_BUCKETS 1453 #define OVECCOUNT (512*3) #define log_error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) #ifdef DEBUG #define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) #else #define log_debug(fmt, ...) ; #endif static unsigned int maxbit=0; /* Define data structures */ typedef struct context_map { char *raw; char *trans; } context_map_t; typedef struct context_map_node { char *key; context_map_t *map; struct context_map_node *next; } context_map_node_t; typedef struct affix { char *text; struct affix *next; } affix_t; typedef struct word { char *text; ebitmap_t cat; ebitmap_t normal; ebitmap_t inverse; struct word *next; } word_t; typedef struct word_group { char *name; char *whitespace; char *join; affix_t *prefixes; affix_t *suffixes; word_t *words; pcre *prefix_regexp; pcre *word_regexp; pcre *suffix_regexp; ebitmap_t def; word_t **sword; unsigned int sword_len; struct word_group *next; } word_group_t; typedef struct base_classification { char *trans; mls_level_t *level; struct base_classification *next; } base_classification_t; typedef struct domain { char *name; context_map_node_t *raw_to_trans[N_BUCKETS]; context_map_node_t *trans_to_raw[N_BUCKETS]; base_classification_t *base_classifications; word_group_t *groups; pcre *base_classification_regexp; struct domain *next; } domain_t; static domain_t *domains; typedef struct sens_constraint { char op; char *text; unsigned int sens; ebitmap_t cat; struct sens_constraint *next; } sens_constraint_t; static sens_constraint_t *sens_constraints; typedef struct cat_constraint { char op; char *text; int nbits; ebitmap_t mask; ebitmap_t cat; struct cat_constraint *next; } cat_constraint_t; static cat_constraint_t *cat_constraints; unsigned int hash(const char *str) { unsigned int hash = 5381; int c; while ((c = *(unsigned const char *)str++)) hash = ((hash << 5) + hash) + c; return hash; } static int add_to_hashtable(context_map_node_t **table, char *key, context_map_t *map) { unsigned int bucket = hash(key) % N_BUCKETS; context_map_node_t **n; for (n = &table[bucket]; *n; n = &(*n)->next) ; *n = malloc(sizeof(context_map_node_t)); if (! *n) goto err; (*n)->key = key; (*n)->map = map; (*n)->next = NULL; return 0; err: syslog(LOG_ERR, "add_to_hashtable: allocation error"); return -1; } static int numdigits(unsigned int n) { int count = 1; while ((n = n / 10)) count++; return count; } static int parse_category(ebitmap_t *e, const char *raw, int allowinverse) { int inverse = 0; unsigned int low, high; while (*raw) { if (allowinverse && *raw == '~') { inverse = !inverse; raw++; continue; } if (sscanf(raw,"c%u", &low) != 1) return -1; raw += numdigits(low) + 1; if (*raw == '.') { raw++; if (sscanf(raw,"c%u", &high) != 1) return -1; raw += numdigits(high) + 1; } else { high = low; } while (low <= high) { if (low >= maxbit) maxbit = low + 1; if (ebitmap_set_bit(e, low, inverse ? 0 : 1) < 0) return -1; low++; } if (*raw == ',') { raw++; inverse = 0; } else if (*raw != '\0') { return -1; } } return 0; } int parse_ebitmap(ebitmap_t *e, ebitmap_t *def, const char *raw) { int rc = ebitmap_cpy(e, def); if (rc < 0) return rc; rc = parse_category(e, raw, 1); if (rc < 0) return rc; return 0; } mls_level_t * parse_raw(const char *raw) { mls_level_t *mls = calloc(1, sizeof(mls_level_t)); if (!mls) goto err; if (sscanf(raw,"s%u", &mls->sens) != 1) goto err; raw += numdigits(mls->sens) + 1; if (*raw == ':') { raw++; if (parse_category(&mls->cat, raw, 0) < 0) goto err; } else if (*raw != '\0') { goto err; } return mls; err: ebitmap_destroy(&mls->cat); free(mls); return NULL; } void destroy_word(word_t **list, word_t *word) { if (!word) { return; } for (; list && *list; list = &(*list)->next) { if (*list == word) { *list = word->next; break; } } free(word->text); ebitmap_destroy(&word->cat); ebitmap_destroy(&word->normal); ebitmap_destroy(&word->inverse); memset(word, 0, sizeof(word_t)); free(word); } word_t * create_word(word_t **list, const char *text) { word_t *w = calloc(1, sizeof(word_t)); if (!w) { goto err; } w->text = strdup(text); if (!w->text) { goto err; } if (list) { for (; *list; list = &(*list)->next) ; *list = w; } return w; err: log_error("create_word: allocation error %s", strerror(errno)); destroy_word(NULL, w); return NULL; } void destroy_group(word_group_t **list, word_group_t *group) { for (; list && *list; list = &(*list)->next) { if (*list == group) { *list = group->next; break; } } while(group->prefixes) { affix_t *next = group->prefixes->next; free(group->prefixes->text); free(group->prefixes); group->prefixes=next; } while(group->suffixes) { affix_t *next = group->suffixes->next; free(group->suffixes->text); free(group->suffixes); group->suffixes=next; } while(group->words) destroy_word(&group->words, group->words); free(group->whitespace); free(group->name); free(group->sword); free(group->join); pcre_free(group->prefix_regexp); pcre_free(group->word_regexp); pcre_free(group->suffix_regexp); ebitmap_destroy(&group->def); free(group); } word_group_t * create_group(word_group_t **list, const char *name) { word_group_t *group = calloc(1, sizeof(word_group_t)); if (!group) return NULL; group->name = strdup(name); if (!group->name) { goto err; } group->join = strdup(" "); if (!group->join) { goto err; } group->whitespace = strdup(" "); if (!group->whitespace) { goto err; } group->sword = NULL; if (list) { for (; *list; list = &(*list)->next) ; *list = group; } return group; err: log_error("allocation error %s", strerror(errno)); destroy_group(NULL, group); return NULL; } void destroy_domain(domain_t *domain) { int i; unsigned int rt = 0, tr = 0; for (i=0; i < N_BUCKETS; i++) { context_map_node_t *ptr; for (ptr = domain->trans_to_raw[i]; ptr;) { context_map_node_t *t = ptr->next; free(ptr); ptr = t; tr++; } domain->trans_to_raw[i] = NULL; } for (i=0; i < N_BUCKETS; i++) { context_map_node_t *ptr; for (ptr = domain->raw_to_trans[i]; ptr;) { context_map_node_t *t = ptr->next; free(ptr->map->raw); free(ptr->map->trans); free(ptr->map); free(ptr); ptr = t; rt++; } domain->raw_to_trans[i] = NULL; } while (domain->base_classifications) { base_classification_t *next = domain->base_classifications->next; free(domain->base_classifications->trans); ebitmap_destroy(&domain->base_classifications->level->cat); free(domain->base_classifications->level); free(domain->base_classifications); domain->base_classifications = next; } pcre_free(domain->base_classification_regexp); while (domain->groups) destroy_group(&domain->groups, domain->groups); free(domain->name); free(domain); syslog(LOG_INFO, "cache sizes: tr = %u, rt = %u", tr, rt); } domain_t * create_domain(const char *name) { domain_t *domain = calloc(1, sizeof(domain_t)); if (!domain) { goto err; } domain->name = strdup(name); if (!domain->name) { goto err; } domain_t **d = &domains; for (; *d; d = &(*d)->next) ; *d = domain; return domain; err: log_error("allocation error %s", strerror(errno)); destroy_domain(domain); return NULL; } int add_word(word_group_t *group, char *raw, char *trans) { if (strchr(trans,'-')) { log_error("'%s'is invalid because '-' is illegal in modifiers.\n", trans); return -1; } word_t *word = create_word(&group->words, trans); int rc = parse_ebitmap(&word->cat, &group->def, raw); if (rc < 0) { log_error(" syntax error in %s\n", raw); destroy_word(&group->words, word); return -1; } if (ebitmap_andnot(&word->normal, &word->cat, &group->def, maxbit) < 0) return -1; ebitmap_t temp; if (ebitmap_xor(&temp, &word->cat, &group->def) < 0) return -1; if (ebitmap_and(&word->inverse, &temp, &group->def) < 0) return -1; ebitmap_destroy(&temp); return 0; } int add_constraint(char op, char *raw, char *tok) { log_debug("%s\n", "add_constraint"); ebitmap_t empty; ebitmap_init(&empty); if (!raw || !*raw) { syslog(LOG_ERR, "unable to parse line"); return -1; } if (*raw == 's') { sens_constraint_t *constraint = calloc(1, sizeof(sens_constraint_t)); if (!constraint) { log_error("allocation error %s", strerror(errno)); return -1; } if (sscanf(raw,"s%u", &constraint->sens) != 1) { syslog(LOG_ERR, "unable to parse level"); free(constraint); return -1; } if (parse_ebitmap(&constraint->cat, &empty, tok) < 0) { syslog(LOG_ERR, "unable to parse cat"); free(constraint); return -1; } if (asprintf(&constraint->text, "%s%c%s", raw, op, tok) < 0) { log_error("asprintf failed %s", strerror(errno)); return -1; } constraint->op = op; sens_constraint_t **p; for (p= &sens_constraints; *p; p = &(*p)->next) ; *p = constraint; return 0; } else if (*raw == 'c' ) { cat_constraint_t *constraint = calloc(1, sizeof(cat_constraint_t)); if (!constraint) { log_error("allocation error %s", strerror(errno)); return -1; } if (parse_ebitmap(&constraint->mask, &empty, raw) < 0) { syslog(LOG_ERR, "unable to parse mask"); free(constraint); return -1; } if (parse_ebitmap(&constraint->cat, &empty, tok) < 0) { syslog(LOG_ERR, "unable to parse cat"); ebitmap_destroy(&constraint->mask); free(constraint); return -1; } if (asprintf(&constraint->text, "%s%c%s", raw, op, tok) < 0) { log_error("asprintf failed %s", strerror(errno)); return -1; } constraint->nbits = ebitmap_cardinality(&constraint->cat); constraint->op = op; cat_constraint_t **p; for (p= &cat_constraints; *p; p = &(*p)->next) ; *p = constraint; return 0; } else { return -1; } return 0; } int violates_constraints(mls_level_t *l) { int nbits; sens_constraint_t *s; ebitmap_t common; for (s=sens_constraints; s; s=s->next) { if (s->sens == l->sens) { if (ebitmap_and(&common, &s->cat, &l->cat) < 0) return 1; nbits = ebitmap_cardinality(&common); ebitmap_destroy(&common); if (nbits) { char *text = mls_level_to_string(l); syslog(LOG_WARNING, "%s violates %s", text, s->text); free(text); return 1; } } } cat_constraint_t *c; for (c=cat_constraints; c; c=c->next) { if (ebitmap_and(&common, &c->mask, &l->cat) < 0) return 1; nbits = ebitmap_cardinality(&common); ebitmap_destroy(&common); if (nbits > 0) { if (ebitmap_and(&common, &c->cat, &l->cat) < 0) return 1; nbits = ebitmap_cardinality(&common); ebitmap_destroy(&common); if ((c->op == '!' && nbits) || (c->op == '>' && nbits != c->nbits)) { char *text = mls_level_to_string(l); syslog(LOG_WARNING, "%s violates %s (%d,%d)", text, c->text, nbits, c->nbits); free(text); return 1; } } } return 0; } void destroy_sens_constraint(sens_constraint_t **list, sens_constraint_t *constraint) { if (!constraint) { return; } for (; list && *list; list = &(*list)->next) { if (*list == constraint) { *list = constraint->next; break; } } ebitmap_destroy(&constraint->cat); free(constraint->text); memset(constraint, 0, sizeof(sens_constraint_t)); free(constraint); } void destroy_cat_constraint(cat_constraint_t **list, cat_constraint_t *constraint) { if (!constraint) { return; } for (; list && *list; list = &(*list)->next) { if (*list == constraint) { *list = constraint->next; break; } } ebitmap_destroy(&constraint->mask); ebitmap_destroy(&constraint->cat); free(constraint->text); memset(constraint, 0, sizeof(cat_constraint_t)); free(constraint); } static int add_base_classification(domain_t *domain, char *raw, char *trans) { mls_level_t *level = parse_raw(raw); if (level) { base_classification_t **i; base_classification_t *base_classification = calloc(1, sizeof(base_classification_t)); if (!base_classification) { log_error("allocation error %s", strerror(errno)); return -1; } base_classification->trans=strdup(trans); if (!base_classification->trans) { log_error("allocation error %s", strerror(errno)); free(base_classification); return -1; } base_classification->level=level; for (i=&domain->base_classifications; *i; i=&(*i)->next) ; *i = base_classification; return 0; } log_error(" add_base_classification error %s %s\n", raw, trans); return -1; } static int add_cache(domain_t *domain, char *raw, char *trans) { context_map_t *map = calloc(1, sizeof(context_map_t)); if (!map) goto err; map->raw = strdup(raw); if (!map->raw) { goto err; } map->trans = strdup(trans); if (!map->trans) { goto err; } log_debug(" add_cache (%s,%s)\n", raw, trans); if (add_to_hashtable(domain->raw_to_trans, map->raw, map) < 0) goto err; if (add_to_hashtable(domain->trans_to_raw, map->trans, map) < 0) goto err; return 0; err: log_error("%s: allocation error", "add_cache"); return -1; } static context_map_t * find_in_table(context_map_node_t **table, const char *key) { unsigned int bucket = hash(key) % N_BUCKETS; context_map_node_t **n; for (n = &table[bucket]; *n; n = &(*n)->next) if (!strcmp((*n)->key, key)) return (*n)->map; return NULL; } char * trim(char *str, const char *whitespace) { char *p = str + strlen(str); while (p > str && strchr(whitespace, *(p-1)) != NULL) *--p = 0; return str; } char * triml(char *str, const char *whitespace) { char *p = str; while (*p && (strchr(whitespace, *p) != NULL)) p++; return p; } int update(char **p, char *const val) { free (*p); *p = strdup(val); if (!*p) { log_error("allocation error %s", strerror(errno)); return -1; } return 0; } int append(affix_t **affixes, const char *val) { affix_t *affix = calloc(1, sizeof(affix_t)); if (!affix) { goto err; } affix->text = strdup(val); if (!affix->text) goto err; for (;*affixes; affixes = &(*affixes)->next) ; *affixes = affix; return 0; err: log_error("allocation error %s", strerror(errno)); free(affix); return -1; } static int read_translations(const char *filename); /* Process line from translation file. Remove white space and set raw do data before the "=" and tok to data after it Modifies the data pointed to by the buffer parameter */ static int process_trans(char *buffer) { static domain_t *domain; static word_group_t *group; static int base_classification; static int lineno = 0; char op='\0'; lineno++; log_debug("%d: %s", lineno, buffer); /* zap leading whitespace */ buffer = triml(buffer, "\t "); /* Ignore comments */ if (*buffer == '#') return 0; char *comment = strpbrk (buffer, "#"); if (comment) { *comment = '\0'; } /* zap trailing whitespace */ buffer = trim(buffer, "\t \r\n"); if (*buffer == 0) return 0; char *delim = strpbrk (buffer, "=!>"); if (! delim) { syslog(LOG_ERR, "invalid line (no !, = or >) %d", lineno); return -1; } op = *delim; *delim = '\0'; char *raw = buffer; char *tok = delim+1; /* remove trailing/leading whitespace from the split tokens */ trim(raw, "\t "); tok = triml(tok, "\t "); if (! *raw) { syslog(LOG_ERR, "invalid line %d", lineno); return -1; } if (! *tok) { syslog(LOG_ERR, "invalid line %d", lineno); return -1; } /* constraints have different syntax */ if (op == '!' || op == '>') { return add_constraint(op, raw, tok); } if (!strcmp(raw, "Domain")) { domain = create_domain(tok); group = NULL; return 0; } if (!domain) { domain = create_domain("Default"); if (!domain) return -1; group = NULL; } if (!group && (!strcmp(raw, "Whitespace") || !strcmp(raw, "Join") || !strcmp(raw, "Prefix") || !strcmp(raw, "Suffix") || !strcmp(raw, "Default"))) { syslog(LOG_ERR, "expected ModifierGroup declaration on line %d", lineno); return -1; } if (!strcmp(raw, "Include")) { unsigned int n; glob_t g; g.gl_offs = 0; if (glob(tok, GLOB_ERR, NULL, &g) < 0) { globfree(&g); return -1; } for (n=0; n < g.gl_pathc; n++) { if (read_translations(g.gl_pathv[n]) < 0) { globfree(&g); return -1; } } globfree(&g); } else if (!strcmp(raw, "Base")) { base_classification = 1; } else if (!strcmp(raw, "ModifierGroup")) { group = create_group(&domain->groups, tok); if (!group) return -1; base_classification = 0; } else if (!strcmp(raw, "Whitespace")) { if (update (&group->whitespace, tok) < 0) return -1; } else if (!strcmp(raw, "Join")) { if (update (&group->join, tok) < 0) return -1; } else if (!strcmp(raw, "Prefix")) { if (append (&group->prefixes, tok) < 0) return -1; } else if (!strcmp(raw, "Suffix")) { if (append (&group->suffixes, tok) < 0) return -1; } else if (!strcmp(raw, "Default")) { ebitmap_t empty; ebitmap_init(&empty); if (parse_ebitmap(&group->def, &empty, tok) < 0) { syslog(LOG_ERR, "unable to parse Default %d", lineno); return -1; } } else if (group) { if (add_word(group, raw, tok) < 0) { syslog(LOG_ERR, "unable to add base_classification on line %d", lineno); return -1; } } else { if (base_classification) { if (add_base_classification(domain, raw, tok) < 0) { syslog(LOG_ERR, "unable to add base_classification on line %d", lineno); return -1; } } if (add_cache(domain, raw, tok) < 0) return -1; } return 0; } int read_translations(const char *filename) { size_t size = 0; char *buffer = NULL; int rval = 0; FILE *cfg = fopen(filename,"r"); if (!cfg) { syslog(LOG_ERR, "%s file open failed", filename); return -1; } __fsetlocking(cfg, FSETLOCKING_BYCALLER); while (getline(&buffer, &size, cfg) > 0) { if( process_trans(buffer) < 0 ) { syslog(LOG_ERR, "%s file read failed", filename); rval = -1; break; } } free(buffer); fclose(cfg); return rval; } int init_translations(void) { if (is_selinux_mls_enabled() <= 0) return -1; return(read_translations(selinux_translations_path())); } char * extract_range(const security_context_t incon) { context_t con = context_new(incon); if (!con) { syslog(LOG_ERR, "extract_range context_new(%s) failed: %s", incon, strerror(errno)); return NULL; } const char *range = context_range_get(con); if (!range) { syslog(LOG_ERR, "extract_range: context_range_get(%s) failed: %m", incon); context_free(con); return NULL; } char *r = strdup(range); if (!r) { log_error("extract_range: allocation error %s", strerror(errno)); return NULL; } context_free(con); return r; } char * new_context_str(const security_context_t incon, const char *range) { char *rcon = NULL; context_t con = context_new(incon); if (!con) { goto exit; } context_range_set(con, range); rcon = strdup(context_str(con)); if (!rcon) { goto exit; } return rcon; exit: log_error("new_context_str: %s %s", incon, strerror(errno)); return NULL; } char * find_in_hashtable(const char *range, domain_t *domain, context_map_node_t **table) { char *trans = NULL; context_map_t *map = find_in_table(table, range); if (map) { trans = strdup((table == domain->raw_to_trans) ? map->trans: map->raw); if (!trans) { log_error("find_in_hashtable: allocation error %s", strerror(errno)); return NULL; } log_debug(" found %s in hashtable returning %s\n", range, trans); } return trans; } void emit_whitespace(char*buffer, char *whitespace) { strcat(buffer, "["); strcat(buffer, whitespace); strcat(buffer, "]"); } static int string_size(const void *p1, const void *p2) { return strlen(*(char **)p2) - strlen(*(char **)p1); } static int word_size(const void *p1, const void *p2) { word_t *w1 = *(word_t **)p1; word_t *w2 = *(word_t **)p2; int w1_len=strlen(w1->text); int w2_len=strlen(w2->text); if (w1_len == w2_len) return strcmp(w1->text, w2->text); return (w2_len - w1_len); } void build_regexp(pcre **r, char *buffer) { const char *error; int error_offset; if (*r) pcre_free(*r); *r = pcre_compile(buffer, PCRE_CASELESS, &error, &error_offset, NULL); if (error) { log_error("pcre=%s, error=%s\n", buffer, error ? error: "none"); } buffer[0] = '\0'; } int build_regexps(domain_t *domain) { char buffer[1024 * 128]; buffer[0] = '\0'; base_classification_t *bc; word_group_t *g; affix_t *a; word_t *w; size_t n_el, i; for (n_el = 0, bc = domain->base_classifications; bc; bc = bc->next) { n_el++; } char **sortable = calloc(n_el, sizeof(char *)); if (!sortable) { log_error("allocation error %s", strerror(errno)); return -1; } for (i=0, bc = domain->base_classifications; bc; bc = bc->next) { sortable[i++] = bc->trans; } qsort(sortable, n_el, sizeof(char *), string_size); for (i = 0; i < n_el; i++) { strcat(buffer, sortable[i]); if (i < n_el) strcat(buffer,"|"); } free(sortable); log_debug(">>> %s classification regexp=%s\n", domain->name, buffer); build_regexp(&domain->base_classification_regexp, buffer); for (g = domain->groups; g; g = g->next) { if (g->prefixes) { strcat(buffer,"(?:"); for (a = g->prefixes; a; a = a->next) { strcat(buffer, a->text); if (a->next) strcat(buffer,"|"); } strcat(buffer,")"); strcat(buffer,"[ ]+"); log_debug(">>> %s %s prefix regexp=%s\n", domain->name, g->name, buffer); build_regexp(&g->prefix_regexp, buffer); } if (g->prefixes) strcat(buffer, "^"); strcat(buffer, "(?:"); g->sword_len=0; for (w = g->words; w; w = w->next) g->sword_len++; g->sword = calloc(g->sword_len, sizeof(word_t *)); if (!g->sword) { log_error("allocation error %s", strerror(errno)); return -1; } i=0; for (w = g->words; w; w = w->next) g->sword[i++]=w; qsort(g->sword, g->sword_len, sizeof(word_t *), word_size); for (i=0; i < g->sword_len; i++) { if (i) strcat(buffer,"|"); strcat(buffer,"\\b"); strcat(buffer, g->sword[i]->text); strcat(buffer,"\\b"); } if (g->whitespace) { strcat(buffer,"|["); strcat(buffer, g->whitespace); strcat(buffer, "]+"); } strcat(buffer, ")+"); if (g->suffixes) strcat(buffer, "$"); log_debug(">>> %s %s modifier regexp=%s\n", domain->name, g->name, buffer); build_regexp(&g->word_regexp, buffer); if (g->suffixes) { strcat(buffer,"[ ]+"); strcat(buffer,"(?:"); for (a = g->suffixes; a; a = a->next) { strcat(buffer, a->text); if (a->next) strcat(buffer,"|"); } strcat(buffer,")"); log_debug(">>> %s %s suffix regexp=%s\n", domain->name, g->name, buffer); build_regexp(&g->suffix_regexp, buffer); } } return 0; } char * compute_raw_from_trans(const char *level, domain_t *domain) { #ifdef DEBUG struct timeval startTime; gettimeofday(&startTime, 0); #endif int rc = 0; int ovector[OVECCOUNT]; word_group_t *g = NULL; char *work = NULL; char *r = NULL; const char * match = NULL; int work_len; mls_level_t *mraw = NULL; ebitmap_t set, clear, tmp; ebitmap_init(&set); ebitmap_init(&clear); ebitmap_init(&tmp); work = strdup(level); if (!work) { log_error("compute_raw_from_trans: allocation error %s", strerror(errno)); goto err; } work_len = strlen(work); if (!domain->base_classification_regexp) if (build_regexps(domain) < 0) goto err; if (!domain->base_classification_regexp) goto err; log_debug(" compute_raw_from_trans work = %s\n", work); rc = pcre_exec(domain->base_classification_regexp, 0, work, work_len, 0, PCRE_ANCHORED, ovector, OVECCOUNT); if (rc > 0) { match = NULL; pcre_get_substring(work, ovector, rc, 0, &match); log_debug(" compute_raw_from_trans match = %s len = %u\n", match, strlen(match)); base_classification_t *bc; for (bc = domain->base_classifications; bc; bc = bc->next) { if (!strcmp(bc->trans, match)) { log_debug(" compute_raw_from_trans base classification %s matched %s\n", level, bc->trans); mraw = malloc(sizeof(mls_level_t)); if (!mraw) { log_error("allocation error %s", strerror(errno)); goto err; } if (mls_level_cpy(mraw, bc->level) < 0) goto err; break; } } memset(work + ovector[0], '#', ovector[1] - ovector[0]); char *p=work + ovector[0] + ovector[1]; while (*p && (strchr(" ", *p) != NULL)) *p++ = '#'; pcre_free((char *)match); match = NULL; } else { log_debug(" compute_raw_from_trans no base classification matched %s\n", level); } if (mraw == NULL) { goto err; } int complete = 0; int change = 1; while(change && !complete) { change = 0; for (g = domain->groups; g && !change && !complete; g = g->next) { int prefix = 0, suffix = 0; int prefix_offset = 0, prefix_len = 0; int suffix_offset = 0, suffix_len = 0; if (g->prefix_regexp) { rc = pcre_exec(g->prefix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT); if (rc > 0) { prefix = 1; prefix_offset = ovector[0]; prefix_len = ovector[1] - ovector[0]; } } if (g->suffix_regexp) { rc = pcre_exec(g->suffix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT); if (rc > 0) { suffix = 1; suffix_offset = ovector[0]; suffix_len = ovector[1] - ovector[0]; } } /* anchors prefix ^, suffix $ */ if (((!g->prefixes && !g->suffixes) || (g->prefixes && prefix) || (g->suffixes && suffix)) && g->word_regexp) { char *s = work + prefix_offset + prefix_len; int l = (suffix_len ? suffix_offset : work_len) - prefix_len - prefix_offset; rc = pcre_exec(g->word_regexp, 0, s, l, 0, 0, ovector, OVECCOUNT); if (rc > 0) { match = NULL; pcre_get_substring(s, ovector, rc, 0, &match); trim((char *)match, g->whitespace); if (*match) { char *p = triml((char *)match, g->whitespace); while (p && *p) { int plen = strlen(p); unsigned int i; for (i = 0; i < g->sword_len; i++) { word_t *w = g->sword[i]; int wlen = strlen(w->text); if (plen >= wlen && !strncmp(w->text, p, strlen(w->text))){ if (ebitmap_andnot(&set, &w->cat, &g->def, maxbit) < 0) goto err; if (ebitmap_xor(&tmp, &w->cat, &g->def) < 0) goto err; if (ebitmap_and(&clear, &tmp, &g->def) < 0) goto err; if (ebitmap_union(&mraw->cat, &set) < 0) goto err; ebitmap_destroy(&tmp); if (ebitmap_cpy(&tmp, &mraw->cat) < 0) goto err; ebitmap_destroy(&mraw->cat); if (ebitmap_andnot(&mraw->cat, &tmp, &clear, maxbit) < 0) goto err; ebitmap_destroy(&tmp); ebitmap_destroy(&set); ebitmap_destroy(&clear); p += strlen(w->text); change++; break; } } if (i == g->sword_len) { syslog(LOG_ERR, "conversion error"); break; } p = triml(p, g->whitespace); } memset(work + prefix_offset, '#', prefix_len); memset(work + suffix_offset, '#', suffix_len); memset(s + ovector[0], '#', ovector[1] - ovector[0]); } pcre_free((void *)match); match = NULL; } } /* YYY */ complete=1; char *p = work; while(*p) { if (isalnum(*p++)) { complete=0; break; } } } } free(work); if (violates_constraints(mraw)) { complete = 0; } if (complete) r = mls_level_to_string(mraw); mls_level_destroy(mraw); free(mraw); #ifdef DEBUG struct timeval stopTime; gettimeofday(&stopTime, 0); long int ms; if (startTime.tv_usec > stopTime.tv_usec) ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000); else ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000); log_debug(" compute_raw_from_trans in %ld ms'\n", ms); #endif return r; err: mls_level_destroy(mraw); free(mraw); free(work); pcre_free((void *)match); ebitmap_destroy(&tmp); ebitmap_destroy(&set); ebitmap_destroy(&clear); return NULL; } char * compute_trans_from_raw(const char *level, domain_t *domain) { #ifdef DEBUG struct timeval startTime; gettimeofday(&startTime, 0); #endif word_group_t *g; mls_level_t *l = NULL; char *rval = NULL; word_group_t *groups = NULL; ebitmap_t bit_diff, temp, handled, nothandled, unhandled, orig_unhandled; ebitmap_init(&bit_diff); ebitmap_init(&temp); ebitmap_init(&handled); ebitmap_init(¬handled); ebitmap_init(&unhandled); ebitmap_init(&orig_unhandled); if (!level) goto err; l = parse_raw(level); if (!l) goto err; log_debug(" compute_trans_from_raw raw = %s\n", level); /* YYY */ /* check constraints */ if (violates_constraints(l)) { syslog(LOG_ERR, "%s violates constraints", level); goto err; } int doInverse = l->sens > 0; base_classification_t *bc, *last = NULL; int done = 0; for (bc = domain->base_classifications; bc && !done; bc = bc->next) { if (l->sens == bc->level->sens) { /* skip if alias of last bc */ if (last && last->level->sens == bc->level->sens && ebitmap_cmp(&last->level->cat, &bc->level->cat) == 0) continue; /* compute bits not consumed by base classification */ if (ebitmap_xor(&unhandled, &l->cat, &bc->level->cat) < 0) goto err; if (ebitmap_cpy(&orig_unhandled, &unhandled) < 0) goto err; /* prebuild groups */ for (g = domain->groups; g; g = g->next) { word_group_t **t; for (t = &groups; *t; t = &(*t)->next) if (!strcmp(g->name, (*t)->name)) break; if (! *t) { word_group_t *wg = create_group(&groups, g->name); if (g->prefixes) if (append(&wg->prefixes, g->prefixes->text) < 0) goto err; if (g->suffixes) if (append(&wg->suffixes, g->suffixes->text) < 0) goto err; if (g->join) if (update(&wg->join, g->join) < 0) goto err; } } int loops, hamming, change=1; for (loops = 50; ebitmap_cardinality(&unhandled) && loops > 0 && change; loops--) { change = 0; hamming = 10000; if (ebitmap_xor(&handled, &unhandled, &orig_unhandled) < 0) goto err; if (ebitmap_not(¬handled, &handled, maxbit) < 0) goto err; word_group_t *currentGroup = NULL; word_t *currentWord = NULL; for (g = domain->groups; g && hamming; g = g->next) { word_t *w; for (w = g->words; w && hamming; w = w->next) { int cardinality = ebitmap_cardinality(&w->normal); /* If the word is all inverse bits and the level does not have inverse bits - skip */ if (cardinality && !doInverse) { continue; } /* if only unhandled bits are different */ if (ebitmap_or(&temp, &w->normal, &w->inverse) < 0) goto err; if (ebitmap_and(&bit_diff, &temp, ¬handled) < 0) goto err; ebitmap_destroy(&temp); // xor bit_diff handled? if (ebitmap_and(&temp, &bit_diff, &unhandled) < 0) goto err; if (ebitmap_cmp(&bit_diff, &temp)) { int h = ebitmap_hamming_distance(&bit_diff, &unhandled); if (h < hamming) { hamming = h; currentGroup = g; currentWord = w; } } ebitmap_destroy(&bit_diff); ebitmap_destroy(&temp); } } ebitmap_destroy(&handled); ebitmap_destroy(¬handled); if (currentWord) { if (ebitmap_xor(&bit_diff, ¤tWord->cat, &bc->level->cat) < 0) goto err; if (ebitmap_cpy(&temp, &unhandled) < 0) goto err; ebitmap_destroy(&unhandled); if (ebitmap_andnot(&unhandled, &temp, &bit_diff, maxbit) < 0) goto err; ebitmap_destroy(&bit_diff); ebitmap_destroy(&temp); word_group_t **t; for (t = &groups; *t; t = &(*t)->next) if (!strcmp(currentGroup->name, (*t)->name)) break; create_word(&(*t)->words, currentWord->text); change++; } } done = (ebitmap_cardinality(&unhandled) == 0); ebitmap_destroy(&unhandled); ebitmap_destroy(&orig_unhandled); if (done) { char buffer[9999]; buffer[0] = 0; strcat(buffer, bc->trans); strcat(buffer, " "); for (g=groups; g; g = g->next) { if (g->words && g->prefixes) { strcat(buffer, g->prefixes->text); strcat(buffer, " "); } word_t *w; for (w=g->words; w; w = w->next) { strcat(buffer, w->text); if (w->next) strcat(buffer, g->join); } if (g->words && g->suffixes) { strcat(buffer, " "); strcat(buffer, g->suffixes->text); } word_group_t *n = g->next; while(g->words && n) { if (n->words) { strcat(buffer, " "); break; } n = n->next; } } rval = strdup(buffer); if (!rval) { log_error("compute_trans_from_raw: allocation error %s", strerror(errno)); goto err; } } /* clean up */ while (groups) destroy_group(&groups, groups); } last = bc; } if (l) { mls_level_destroy(l); free(l); } #ifdef DEBUG struct timeval stopTime; gettimeofday(&stopTime, 0); long int ms; if (startTime.tv_usec > stopTime.tv_usec) ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000); else ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000); log_debug(" compute_trans_from_raw in %ld ms'\n", ms); #endif return rval; err: while (groups) destroy_group(&groups, groups); mls_level_destroy(l); free(l); return NULL; } int trans_context(const security_context_t incon, security_context_t *rcon) { char *trans = NULL; *rcon = NULL; #ifdef DEBUG struct timeval startTime; gettimeofday(&startTime, 0); #endif log_debug(" trans_context input = %s\n", incon); char *range = extract_range(incon); if (!range) return -1; domain_t *domain = domains; for (;domain; domain = domain->next) { trans = find_in_hashtable(range, domain, domain->raw_to_trans); if (trans) break; /* try split and translate */ char *lrange = NULL, *urange = NULL; char *ltrans = NULL, *utrans = NULL; char *dashp = strchr(range,'-'); if (dashp) { *dashp = 0; lrange = range; urange = dashp+1; } else { trans = compute_trans_from_raw(range, domain); if (trans) if (add_cache(domain, range, trans) < 0) { free(range); return -1; } } if (lrange && urange) { ltrans = find_in_hashtable(lrange, domain, domain->raw_to_trans); if (! ltrans) { ltrans = compute_trans_from_raw(lrange, domain); if (ltrans) { if (add_cache(domain, lrange, ltrans) < 0) { free(range); return -1; } } else { ltrans = strdup(lrange); if (! ltrans) { log_error("strdup failed %s", strerror(errno)); free(range); return -1; } } } utrans = find_in_hashtable(urange, domain, domain->raw_to_trans); if (! utrans) { utrans = compute_trans_from_raw(urange, domain); if (utrans) { if (add_cache(domain, urange, utrans) < 0) { free(ltrans); free(range); return -1; } } else { utrans = strdup(urange); if (! utrans) { log_error("strdup failed %s", strerror(errno)); free(ltrans); free(range); return -1; } } } if (strcmp(ltrans, utrans) == 0) { if (asprintf(&trans, "%s", ltrans) < 0) { log_error("asprintf failed %s", strerror(errno)); free(utrans); free(ltrans); free(range); return -1; } } else { if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) { log_error("asprintf failed %s", strerror(errno)); free(utrans); free(ltrans); free(range); return -1; } } free(ltrans); free(utrans); *dashp = '-'; break; } if (dashp) *dashp = '-'; } if (trans) { *rcon = new_context_str(incon, trans); free(trans); } else { *rcon = new_context_str(incon, range); } free(range); #ifdef DEBUG struct timeval stopTime; gettimeofday(&stopTime, 0); long int ms; if (startTime.tv_usec > stopTime.tv_usec) ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000); else ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000); log_debug(" trans_context input='%s' output='%s in %ld ms'\n", incon, *rcon, ms); #endif return 0; } int untrans_context(const security_context_t incon, security_context_t *rcon) { char *raw = NULL; *rcon = NULL; #ifdef DEBUG struct timeval startTime; gettimeofday(&startTime, 0); #endif log_debug(" untrans_context incon = %s\n", incon); char *range = extract_range(incon); if (!range) return -1; log_debug(" untrans_context range = %s\n", range); domain_t *domain = domains; for (;domain; domain = domain->next) { raw = find_in_hashtable(range, domain, domain->trans_to_raw); if (raw) break; /* try split and translate */ char *lrange = NULL, *urange = NULL; char *lraw = NULL, *uraw = NULL; char *dashp = strchr(range,'-'); if (dashp) { *dashp = 0; lrange = range; urange = dashp+1; } else { raw = compute_raw_from_trans(range, domain); if (raw) { char *canonical = find_in_hashtable(raw, domain, domain->raw_to_trans); if (!canonical) { canonical = compute_trans_from_raw(raw, domain); if (canonical && strcmp(canonical, range)) if (add_cache(domain, raw, canonical) < 0) { free(range); return -1; } } if (canonical) free(canonical); if (add_cache(domain, raw, range) < 0) { free(range); return -1; } } else { log_debug("untrans_context unable to compute raw context %s\n", range); } } if (lrange && urange) { lraw = find_in_hashtable(lrange, domain, domain->trans_to_raw); if (! lraw) { lraw = compute_raw_from_trans(lrange, domain); if (lraw) { char *canonical = find_in_hashtable(lraw, domain, domain->raw_to_trans); if (!canonical) { canonical = compute_trans_from_raw(lraw, domain); if (canonical) if (add_cache(domain, lraw, canonical) < 0) { free(lraw); free(range); return -1; } } if (canonical) free(canonical); if (add_cache(domain, lraw, lrange) < 0) { free(lraw); free(range); return -1; } } else { lraw = strdup(lrange); if (! lraw) { log_error("strdup failed %s", strerror(errno)); free(range); return -1; } } } uraw = find_in_hashtable(urange, domain, domain->trans_to_raw); if (! uraw) { uraw = compute_raw_from_trans(urange, domain); if (uraw) { char *canonical = find_in_hashtable(uraw, domain, domain->raw_to_trans); if (!canonical) { canonical = compute_trans_from_raw(uraw, domain); if (canonical) if (add_cache(domain, uraw, canonical) < 0) { free(uraw); free(lraw); free(range); return -1; } } if (canonical) free(canonical); if (add_cache(domain, uraw, urange) < 0) { free(uraw); free(lraw); free(range); return -1; } } else { uraw = strdup(urange); if (! uraw) { log_error("strdup failed %s", strerror(errno)); free(lraw); free(range); return -1; } } } if (strcmp(lraw, uraw) == 0) { if (asprintf(&raw, "%s", lraw) < 0) { log_error("asprintf failed %s", strerror(errno)); free(uraw); free(lraw); free(range); return -1; } } else { if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) { log_error("asprintf failed %s", strerror(errno)); free(uraw); free(lraw); free(range); return -1; } } free(lraw); free(uraw); *dashp = '-'; break; } if (dashp) *dashp = '-'; } if (raw) { *rcon = new_context_str(incon, raw); free(raw); } else { *rcon = new_context_str(incon, range); } free(range); #ifdef DEBUG struct timeval stopTime; gettimeofday(&stopTime, 0); long int ms; if (startTime.tv_usec > stopTime.tv_usec) ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000); else ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000); log_debug(" untrans_context input='%s' output='%s' n %ld ms\n", incon, *rcon, ms); #endif return 0; } void finish_context_translations(void) { while(domains) { domain_t *next = domains->next; destroy_domain(domains); domains = next; } while(sens_constraints) { sens_constraint_t *next = sens_constraints->next; destroy_sens_constraint(&sens_constraints, sens_constraints); sens_constraints = next; } while(cat_constraints) { cat_constraint_t *next = cat_constraints->next; destroy_cat_constraint(&cat_constraints, cat_constraints); cat_constraints = next; } } mcstrans/src/mcstrans.h0100644 0000000 0000000 00000000503 13756670066 014247 0ustar000000000 0000000 /* Copyright (c) 2006 Trusted Computer Solutions, Inc. */ #include extern int init_translations(void); extern void finish_context_translations(void); extern int trans_context(const security_context_t, security_context_t *); extern int untrans_context(const security_context_t, security_context_t *); mcstrans/src/mcstrans.init0100644 0000000 0000000 00000003361 13756670066 014770 0ustar000000000 0000000 #!/bin/bash # # mcstransd This starts and stops mcstransd # # chkconfig: - 08 87 # description: This starts the SELinux Context Translation System Daemon # # processname: /sbin/mcstransd # pidfile: /var/run/mcstransd.pid # # Return values according to LSB for all commands but status: # 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - insufficient privilege # 5 - program is not installed # 6 - program is not configured # 7 - program is not running PATH=/sbin:/bin:/usr/bin:/usr/sbin prog="mcstransd" lockfile=/var/lock/subsys/$prog # Source function library. . /etc/init.d/functions # Allow anyone to run status if [ "$1" = "status" ] ; then status $prog RETVAL=$? exit $RETVAL fi # Check that we are root ... so non-root users stop here test $EUID = 0 || exit 4 # If selinux is not enabled, return success test -x /usr/sbin/selinuxenabled && /usr/sbin/selinuxenabled || exit 0 RETVAL=0 start(){ test -x /sbin/mcstransd || exit 5 echo -n $"Starting $prog: " if status $prog > /dev/null; then echo -n $"$prog: already running" failure echo return 1 fi unset HOME MAIL USER USERNAME daemon $prog "$EXTRAOPTIONS" RETVAL=$? echo if test $RETVAL = 0 ; then touch $lockfile fi return $RETVAL } stop(){ echo -n $"Stopping $prog: " killproc $prog RETVAL=$? echo rm -f $lockfile return $RETVAL } restart(){ stop start } condrestart(){ [ -e $lockfile ] && restart return 0 } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|force-reload) restart ;; condrestart) condrestart ;; *) echo $"Usage: $0 {start|stop|status|restart|force-reload|condrestart}" RETVAL=3 esac exit $RETVAL mcstrans/src/mcstrans.service0100644 0000000 0000000 00000000315 13756670066 015461 0ustar000000000 0000000 [Unit] Description=Translates SELinux MCS/MLS labels to human readable form ConditionSecurity=selinux [Service] ExecStart=/sbin/mcstransd -f RuntimeDirectory=setrans [Install] WantedBy=multi-user.target mcstrans/src/mcstransd.c0100644 0000000 0000000 00000031016 13756670066 014411 0ustar000000000 0000000 /* Copyright (c) 2006 Trusted Computer Solutions, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mcstrans.h" #ifdef UNUSED #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else # define UNUSED(x) x #endif #define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix" #define SETRANS_INIT 1 #define RAW_TO_TRANS_CONTEXT 2 #define TRANS_TO_RAW_CONTEXT 3 #define RAW_CONTEXT_TO_COLOR 4 #define MAX_DATA_BUF 4096 #define MAX_DESCRIPTORS 8192 #ifdef DEBUG //#define log_debug(fmt, ...) syslog(LOG_DEBUG, fmt, __VA_ARGS__) #define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) #else #define log_debug(fmt, ...) ; #endif extern int init_translations(void); extern void finish_context_translations(void); extern int trans_context(const security_context_t, security_context_t *); extern int untrans_context(const security_context_t, security_context_t *); extern int init_colors(void); extern void finish_context_colors(void); extern int raw_color(const security_context_t, char **); #define SETRANSD_PATHNAME "/sbin/mcstransd" /* name of program (for error messages) */ #define SETRANSD_PROGNAME "mcstransd" static int sockfd = -1; /* socket we are listening on */ static volatile int restart_daemon = 0; static void cleanup_exit(int ret) __attribute__ ((noreturn)); static void cleanup_exit(int ret) { finish_context_colors(); finish_context_translations(); if (sockfd >=0) (void)unlink(SETRANS_UNIX_SOCKET); log_debug("%s\n", "cleanup_exit"); exit(ret); } static void clean_exit(void); static __attribute__((noreturn)) void clean_exit(void) { log_debug("%s\n", "clean_exit"); cleanup_exit(0); } static int send_response(int fd, uint32_t function, char *data, int32_t ret_val) { struct iovec resp_hdr[3]; uint32_t data_size; struct iovec resp_data; ssize_t count; if (!data) data = (char *)""; data_size = strlen(data) + 1; resp_hdr[0].iov_base = &function; resp_hdr[0].iov_len = sizeof(function); resp_hdr[1].iov_base = &data_size; resp_hdr[1].iov_len = sizeof(data_size); resp_hdr[2].iov_base = &ret_val; resp_hdr[2].iov_len = sizeof(ret_val); while (((count = writev(fd, resp_hdr, 3)) < 0) && (errno == EINTR)); if (count != (sizeof(function) + sizeof(data_size) + sizeof(ret_val))) { syslog(LOG_ERR, "Failed to write response header"); return -1; } resp_data.iov_base = data; resp_data.iov_len = data_size; while (((count = writev(fd, &resp_data, 1)) < 0) && (errno == EINTR)); if (count < 0 || (size_t)count != data_size) { syslog(LOG_ERR, "Failed to write response data"); return -1; } return ret_val; } static int get_peer_pid(int fd, pid_t *pid) { int ret; socklen_t size = sizeof(struct ucred); struct ucred peercred; /* get the context of the requesting process */ ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &size); if (ret < 0) { syslog(LOG_ERR, "Failed to get PID of client process"); return -1; } *pid = peercred.pid; return ret; } static int process_request(int fd, uint32_t function, char *data1, char *UNUSED(data2)) { int32_t result; char *out = NULL; int ret; switch (function) { case SETRANS_INIT: result = 0; ret = send_response(fd, function, NULL, result); break; case RAW_TO_TRANS_CONTEXT: result = trans_context(data1, &out); ret = send_response(fd, function, out, result); break; case TRANS_TO_RAW_CONTEXT: result = untrans_context(data1, &out); ret = send_response(fd, function, out, result); break; case RAW_CONTEXT_TO_COLOR: result = raw_color(data1, &out); ret = send_response(fd, function, out, result); break; default: result = -1; ret = -1; break; } if (result) { pid_t pid = 0; get_peer_pid(fd, &pid); syslog(LOG_ERR, "Invalid request func=%d from=%u", function, pid); } free(out); return ret; } static int service_request(int fd) { struct iovec req_hdr[3]; uint32_t function; uint32_t data1_size; uint32_t data2_size; struct iovec req_data[2]; char *data1; char *data2; int ret; ssize_t count; req_hdr[0].iov_base = &function; req_hdr[0].iov_len = sizeof(function); req_hdr[1].iov_base = &data1_size; req_hdr[1].iov_len = sizeof(data1_size); req_hdr[2].iov_base = &data2_size; req_hdr[2].iov_len = sizeof(data2_size); while (((count = readv(fd, req_hdr, 3)) < 0) && (errno == EINTR)); if (count <= 0) { return 1; } if (count != (sizeof(function) + sizeof(data1_size) + sizeof(data2_size) )) { log_debug("Failed to read request header %d != %u\n",(int)count, (unsigned)(sizeof(function) + sizeof(data1_size) + sizeof(data2_size) )); return -1; } if (!data1_size || !data2_size || data1_size > MAX_DATA_BUF || data2_size > MAX_DATA_BUF ) { log_debug("Header invalid data1_size=%u data2_size=%u\n", data1_size, data2_size); return -1; } data1 = malloc(data1_size); if (!data1) { log_debug("Could not allocate %d bytes\n", data1_size); return -1; } data2 = malloc(data2_size); if (!data2) { free(data1); log_debug("Could not allocate %d bytes\n", data2_size); return -1; } req_data[0].iov_base = data1; req_data[0].iov_len = data1_size; req_data[1].iov_base = data2; req_data[1].iov_len = data2_size; while (((count = readv(fd, req_data, 2)) < 0) && (errno == EINTR)); if (count <= 0 || (size_t)count != (data1_size + data2_size) || data1[data1_size - 1] != '\0' || data2[data2_size - 1] != '\0') { free(data1); free(data2); log_debug("Failed to read request data (%d)\n", (int)count); return -1; } ret = process_request(fd, function, data1, data2); free(data1); free(data2); return ret; } static int add_pollfd(struct pollfd **ufds, int *nfds, int connfd) { int ii = 0; /* First see if we can find an already invalidated ufd */ for (ii = 0; ii < *nfds; ii++) { if ((*ufds)[ii].fd == -1) break; } if (ii == *nfds) { struct pollfd *tmp = (struct pollfd *)realloc(*ufds, (*nfds+1)*sizeof(struct pollfd)); if (!tmp) { syslog(LOG_ERR, "realloc failed for %d fds", *nfds+1); return -1; } *ufds = tmp; (*nfds)++; } (*ufds)[ii].fd = connfd; (*ufds)[ii].events = POLLIN|POLLPRI; (*ufds)[ii].revents = 0; return 0; } static void adj_pollfds(struct pollfd **ufds, int *nfds) { int ii, jj; jj = 0; for (ii = 0; ii < *nfds; ii++) { if ((*ufds)[ii].fd != -1) { if (jj < ii) (*ufds)[jj] = (*ufds)[ii]; jj++; } } *nfds = jj; } static int process_events(struct pollfd **ufds, int *nfds) { int ii = 0; int ret = 0; for (ii = 0; ii < *nfds; ii++) { short revents = (*ufds)[ii].revents; int connfd = (*ufds)[ii].fd; if (revents & (POLLIN | POLLPRI)) { if (connfd == sockfd) { /* Probably received a connection */ if ((connfd = accept(sockfd, NULL, NULL)) < 0) { syslog(LOG_ERR, "accept() failed: %m"); return -1; } if (add_pollfd(ufds, nfds, connfd)) { syslog(LOG_ERR, "Failed to add fd (%d) to poll list\n", connfd); return -1; } } else { ret = service_request(connfd); if (ret) { if (ret < 0) { syslog(LOG_ERR, "Servicing of request " "failed for fd (%d)\n", connfd); } /* Setup pollfd for deletion later. */ (*ufds)[ii].fd = -1; close(connfd); /* So we don't get bothered later */ revents = revents & ~(POLLHUP); } } revents = revents & ~(POLLIN | POLLPRI); } if (revents & POLLHUP) { log_debug("The connection with fd (%d) hung up\n", connfd); /* Set the pollfd up for deletion later. */ (*ufds)[ii].fd = -1; close(connfd); revents = revents & ~(POLLHUP); } if (revents) { syslog(LOG_ERR, "Unknown/error events (%x) encountered" " for fd (%d)\n", revents, connfd); /* Set the pollfd up for deletion later. */ (*ufds)[ii].fd = -1; close(connfd); } (*ufds)[ii].revents = 0; } /* Delete any invalidated ufds */ adj_pollfds(ufds, nfds); return 0; } static void process_connections(void) __attribute__ ((noreturn)); static void process_connections(void) { int ret = 0; int nfds = 1; struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd)); if (!ufds) { syslog(LOG_ERR, "Failed to allocate a pollfd"); cleanup_exit(1); } ufds[0].fd = sockfd; ufds[0].events = POLLIN|POLLPRI; ufds[0].revents = 0; while (1) { if (restart_daemon) { syslog(LOG_NOTICE, "Reload Translations"); finish_context_colors(); finish_context_translations(); if (init_translations()) { syslog(LOG_ERR, "Failed to initialize label translations"); cleanup_exit(1); } if (init_colors()) { syslog(LOG_ERR, "Failed to initialize color translations"); syslog(LOG_ERR, "No color information will be available"); } restart_daemon = 0; } ret = poll(ufds, nfds, -1); if (ret < 0) { if (errno == EINTR) { continue; } syslog(LOG_ERR, "poll() failed: %m"); cleanup_exit(1); } ret = process_events(&ufds, &nfds); if (ret) { syslog(LOG_ERR, "Error processing events"); cleanup_exit(1); } } } static void sigterm_handler(int sig) __attribute__ ((noreturn)); static void sigterm_handler(int UNUSED(sig)) { cleanup_exit(0); } static void sighup_handler(int UNUSED(sig)) { restart_daemon = 1; } static void initialize(void) { struct sigaction act; struct sockaddr_un addr; struct rlimit rl ; if (init_translations()) { syslog(LOG_ERR, "Failed to initialize label translations"); cleanup_exit(1); } if (init_colors()) { syslog(LOG_ERR, "Failed to initialize color translations"); syslog(LOG_ERR, "No color information will be available"); } /* the socket will be unlinked when the daemon terminates */ act.sa_handler = sigterm_handler; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGINT); sigaddset(&act.sa_mask, SIGQUIT); sigaddset(&act.sa_mask, SIGTERM); sigaddset(&act.sa_mask, SIGHUP); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGTERM, &act, NULL); /* restart the daemon on SIGHUP */ act.sa_handler = sighup_handler; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGINT); sigaddset(&act.sa_mask, SIGQUIT); sigaddset(&act.sa_mask, SIGTERM); act.sa_flags = 0; sigaction(SIGHUP, &act, NULL); /* ignore SIGPIPE (in case a client terminates after sending request) */ act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGPIPE, &act, NULL); atexit(clean_exit); sockfd = socket(PF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) { syslog(LOG_ERR, "socket() failed: %m"); cleanup_exit(1); } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path) - 1); (void)unlink(SETRANS_UNIX_SOCKET); if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "bind() failed: %m"); cleanup_exit(1); } if (listen(sockfd, SOMAXCONN) < 0) { syslog(LOG_ERR, "listen() failed: %m"); cleanup_exit(1); } if (chmod(SETRANS_UNIX_SOCKET, S_IRWXU | S_IRWXG | S_IRWXO)) { syslog(LOG_ERR, "chmod() failed: %m"); cleanup_exit(1); } /* Raise the rlimit for file descriptors... */ rl.rlim_max = MAX_DESCRIPTORS; rl.rlim_cur = MAX_DESCRIPTORS; setrlimit(RLIMIT_NOFILE, &rl); } void dropprivs(void) { cap_t new_caps; new_caps = cap_init(); if (cap_set_proc(new_caps)) { syslog(LOG_ERR, "Error dropping capabilities, aborting: %s\n", strerror(errno)); cleanup_exit(-1); } cap_free(new_caps); } static void usage(char *program) { printf("%s [-f] [-h] \n", program); } int main(int argc, char *argv[]) { int opt; int do_fork = 1; while ((opt = getopt(argc, argv, "hf")) > 0) { switch (opt) { case 'f': do_fork = 0; break; case 'h': usage(argv[0]); exit(0); break; case '?': usage(argv[0]); exit(-1); } } #ifndef DEBUG /* Make sure we are root */ if (getuid() != 0) { syslog(LOG_ERR, "You must be root to run this program.\n"); return 4; } #endif openlog(SETRANSD_PROGNAME, 0, LOG_DAEMON); syslog(LOG_NOTICE, "%s starting", argv[0]); initialize(); #ifndef DEBUG dropprivs(); /* run in the background as a daemon */ if (do_fork && daemon(0, 0)) { syslog(LOG_ERR, "daemon() failed: %m"); cleanup_exit(1); } #endif syslog(LOG_NOTICE, "%s initialized", argv[0]); process_connections(); /* we should never get here */ return 1; } mcstrans/src/mls_level.c0100644 0000000 0000000 00000005743 13756670066 014405 0ustar000000000 0000000 #include #include "mls_level.h" #include mls_level_t *mls_level_from_string(char *mls_context) { char delim; char *scontextp, *p, *lptr; mls_level_t *l; if (!mls_context) { return NULL; } l = (mls_level_t *) calloc(1, sizeof(mls_level_t)); /* Extract low sensitivity. */ scontextp = p = mls_context; while (*p && *p != ':' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; if (*scontextp != 's') goto err; l->sens = atoi(scontextp + 1); if (delim == ':') { /* Extract category set. */ while (1) { scontextp = p; while (*p && *p != ',' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; /* Separate into level if exists */ if ((lptr = strchr(scontextp, '.')) != NULL) { /* Remove '.' */ *lptr++ = 0; } if (*scontextp != 'c') goto err; int bit = atoi(scontextp + 1); if (ebitmap_set_bit(&l->cat, bit, 1)) goto err; /* If level, set all categories in level */ if (lptr) { if (*lptr != 'c') goto err; int ubit = atoi(lptr + 1); int i; for (i = bit + 1; i <= ubit; i++) { if (ebitmap_set_bit (&l->cat, i, 1)) goto err; } } if (delim != ',') break; } } return l; err: free(l); return NULL; } /* * Return the length in bytes for the MLS fields of the * security context string representation of `context'. */ unsigned int mls_compute_string_len(mls_level_t *l) { unsigned int len = 0; char temp[16]; unsigned int i, level = 0; ebitmap_node_t *cnode; if (!l) return 0; len += snprintf(temp, sizeof(temp), "s%d", l->sens); ebitmap_for_each_bit(&l->cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (level) { level++; continue; } len++; /* : or ,` */ len += snprintf(temp, sizeof(temp), "c%d", i); level++; } else { if (level > 1) len += snprintf(temp, sizeof(temp), ".c%d", i-1); level = 0; } } /* Handle case where last category is the end of level */ if (level > 1) len += snprintf(temp, sizeof(temp), ".c%d", i-1); return len; } char *mls_level_to_string(mls_level_t *l) { unsigned int wrote_sep, len = mls_compute_string_len(l); unsigned int i, level = 0; ebitmap_node_t *cnode; wrote_sep = 0; if (len == 0) return NULL; char *result = (char *)malloc(len + 1); char *p = result; p += sprintf(p, "s%d", l->sens); /* categories */ ebitmap_for_each_bit(&l->cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (level) { level++; continue; } if (!wrote_sep) { *p++ = ':'; wrote_sep = 1; } else *p++ = ','; p += sprintf(p, "c%d", i); level++; } else { if (level > 1) { if (level > 2) *p++ = '.'; else *p++ = ','; p += sprintf(p, "c%d", i-1); } level = 0; } } /* Handle case where last category is the end of level */ if (level > 1) { if (level > 2) *p++ = '.'; else *p++ = ','; p += sprintf(p, "c%d", i-1); } *(result + len) = 0; return result; } mcstrans/src/mls_level.h0100644 0000000 0000000 00000000367 13756670066 014407 0ustar000000000 0000000 #ifndef __mls_level_h__ #define __mls_level_h__ #include unsigned int mls_compute_string_len(mls_level_t *r); mls_level_t *mls_level_from_string(char *mls_context); char *mls_level_to_string(mls_level_t *r); #endif mcstrans/utils/0040755 0000000 0000000 00000000000 13756670066 012622 5ustar000000000 0000000 mcstrans/utils/.gitignore0100644 0000000 0000000 00000000024 13756670066 014603 0ustar000000000 0000000 transcon untranscon mcstrans/utils/Makefile0100644 0000000 0000000 00000001631 13756670066 014260 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr SBINDIR ?= $(PREFIX)/sbin TARGETS=transcon untranscon # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there # is no need to define a value for LDLIBS_LIBSEPOLA ifeq ($(LIBSEPOLA),) LDLIBS_LIBSEPOLA := -l:libsepol.a endif all: $(TARGETS) transcon: transcon.o ../src/mcstrans.o ../src/mls_level.o $(LIBSEPOLA) $(CC) $(LDFLAGS) -o $@ $^ -lpcre -lselinux $(LDLIBS_LIBSEPOLA) untranscon: untranscon.o ../src/mcstrans.o ../src/mls_level.o $(LIBSEPOLA) $(CC) $(LDFLAGS) -o $@ $^ -lpcre -lselinux $(LDLIBS_LIBSEPOLA) %.o: %.c $(CC) $(CFLAGS) -D_GNU_SOURCE -I../src -fPIE -c -o $@ $< install: all -mkdir -p $(DESTDIR)$(SBINDIR) install -m 755 $(TARGETS) $(DESTDIR)$(SBINDIR) test: ./mlstrans-test-runner.py ../test/*.test clean: rm -f $(TARGETS) *.o *~ \#* relabel: mcstrans/utils/callgrind-mcstransd0100644 0000000 0000000 00000000317 13756670066 016476 0ustar000000000 0000000 #!/bin/bash service mcstrans stop cd ~root runcon -u system_u -r system_r -t setrans_t -l s15:c0.c1023 -- valgrind --tool=callgrind /usr/src/redhat/BUILD/*/src/mcstransd run_init /etc/init.d/mcstrans start mcstrans/utils/transcon.c0100644 0000000 0000000 00000001076 13756670066 014616 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "mcstrans.h" static __attribute__((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s context\n", progname); exit(1); } int main(int argc, char **argv) { security_context_t scon; if ( argc != 2 ) usage(argv[0]); if (init_translations()==0) { if(trans_context(argv[1],&scon) == 0) { printf("%s\n", scon); freecon(scon); return 0; } } printf("Failed\n"); return -1; } mcstrans/utils/untranscon.c0100644 0000000 0000000 00000001052 13756670066 015153 0ustar000000000 0000000 #include #include #include #include #include #include #include #include "mcstrans.h" static __attribute__((__noreturn__)) void usage(const char *progname) { fprintf(stderr, "usage: %s context\n", progname); exit(1); } int main(int argc, char **argv) { security_context_t scon; if ( argc != 2 ) usage(argv[0]); if (init_translations()==0) { if(untrans_context(argv[1],&scon) == 0) { printf("%s\n", scon); freecon(scon); return 0; } } return -1; } mcstrans/utils/valgrind-mcstransd0100644 0000000 0000000 00000000416 13756670066 016345 0ustar000000000 0000000 #!/bin/bash service mcstrans stop #valgrind -v --leak-check=full --show-reachable=yes ../src/mcstransd runcon -u system_u -r system_r -t setrans_t -l s15:c0.c1023 -- valgrind -v --leak-check=full --show-reachable=yes ../src/mcstransd run_init /etc/init.d/mcstrans start policycoreutils/0040755 0000000 0000000 00000000000 13756670066 013061 5ustar000000000 0000000 policycoreutils/.gitignore0100644 0000000 0000000 00000000337 13756670066 015051 0ustar000000000 0000000 load_policy/load_policy newrole/newrole run_init/open_init_pty run_init/run_init secon/secon semodule/semodule sestatus/sestatus setfiles/restorecon setfiles/restorecon_xattr setfiles/setfiles setsebool/setsebool hll/pp/pp policycoreutils/.tx/0040755 0000000 0000000 00000000000 13756670066 013572 5ustar000000000 0000000 policycoreutils/.tx/config0100644 0000000 0000000 00000000247 13756670066 014762 0ustar000000000 0000000 [main] host = https://www.transifex.com [policycoreutils.policycoreutils] file_filter = po/.po source_file = po/policycoreutils.pot source_lang = en type = PO policycoreutils/COPYING0100644 0000000 0000000 00000043131 13756670066 014113 0ustar000000000 0000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. policycoreutils/Makefile0100644 0000000 0000000 00000000341 13756670066 014514 0ustar000000000 0000000 SUBDIRS = setfiles load_policy newrole run_init secon sestatus semodule setsebool scripts po man hll all install relabel clean indent: @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done test: policycoreutils/VERSION0100644 0000000 0000000 00000000004 13756670066 014120 0ustar000000000 0000000 2.9 policycoreutils/hll/0040755 0000000 0000000 00000000000 13756670066 013640 5ustar000000000 0000000 policycoreutils/hll/Makefile0100644 0000000 0000000 00000000211 13756670066 015267 0ustar000000000 0000000 SUBDIRS = pp all install relabel clean indent: @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done test: policycoreutils/hll/pp/0040755 0000000 0000000 00000000000 13756670066 014257 5ustar000000000 0000000 policycoreutils/hll/pp/Makefile0100644 0000000 0000000 00000001006 13756670066 015711 0ustar000000000 0000000 # Installation directories. PREFIX ?= /usr LIBEXECDIR ?= $(PREFIX)/libexec HLLDIR ?= $(LIBEXECDIR)/selinux/hll CFLAGS ?= -Werror -Wall -W override LDLIBS += -lsepol PP_SRCS = $(sort $(wildcard *.c)) PP_OBJS = $(patsubst %.c,%.o,$(PP_SRCS)) all: pp pp: $(PP_OBJS) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) %.o: %.c $(CC) $(CFLAGS) -c -o $@ $^ install: all -mkdir -p $(DESTDIR)$(HLLDIR) install -m 755 pp $(DESTDIR)$(HLLDIR) relabel: clean: -rm -f pp $(PP_OBJS) indent: ../../scripts/Lindent $(wildcard *.[ch]) policycoreutils/hll/pp/pp.c0100644 0000000 0000000 00000007633 13756670066 015050 0ustar000000000 0000000 /* * Copyright (C) 2014 Tresys Technology, LLC * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include char *progname; __attribute__ ((format(printf, 1, 2))) static void log_err(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(stderr, fmt, argptr) < 0) { _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(stderr, "\n") < 0) { _exit(EXIT_FAILURE); } } static __attribute__((__noreturn__)) void usage(int err) { fprintf(stderr, "Usage: %s [OPTIONS] [IN_FILE [OUT_FILE]]\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Read an SELinux policy package (.pp) and output the equivilent CIL.\n"); fprintf(stderr, "If IN_FILE is not provided or is -, read SELinux policy package from\n"); fprintf(stderr, "standard input. If OUT_FILE is not provided or is -, output CIL to\n"); fprintf(stderr, "standard output.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -h, --help print this message and exit\n"); exit(err); } int main(int argc, char **argv) { int rc = -1; int opt; static struct option long_opts[] = { { "help", 0, NULL, 'h' }, { NULL, 0, NULL, 0 } }; struct sepol_module_package *mod_pkg = NULL; const char *ifile = NULL; const char *ofile = NULL; FILE *in = NULL; FILE *out = NULL; // ignore sigpipe so we can check the return code of write, and potentially // return a more helpful error message signal(SIGPIPE, SIG_IGN); progname = basename(argv[0]); while ((opt = getopt_long(argc, argv, "h", long_opts, NULL)) != -1) { switch (opt) { case 'h': usage(0); case '?': default: usage(1); } } if (argc >= optind + 1 && strcmp(argv[1], "-") != 0) { ifile = argv[1]; in = fopen(ifile, "rb"); if (in == NULL) { log_err("Failed to open %s: %s", ifile, strerror(errno)); rc = -1; goto exit; } } else { ifile = "stdin"; in = stdin; } if (argc >= optind + 2 && strcmp(argv[2], "-") != 0) { ofile = argv[2]; out = fopen(ofile, "w"); if (out == NULL) { log_err("Failed to open %s: %s", ofile, strerror(errno)); rc = -1; goto exit; } } else { out = stdout; } if (argc >= optind + 3) { log_err("Too many arguments"); usage(1); } rc = sepol_ppfile_to_module_package(in, &mod_pkg); if (rc != 0) { goto exit; } fclose(in); in = NULL; if (ofile) { char *mod_name = mod_pkg->policy->p.name; char *cil_path = strdup(ofile); if (cil_path == NULL) { log_err("No memory available for strdup\n"); rc = -1; goto exit; } char *cil_name = basename(cil_path); char *separator = strrchr(cil_name, '.'); if (separator) { *separator = '\0'; } if (mod_name && strcmp(mod_name, cil_name) != 0) { fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", ifile, mod_name, cil_name); } free(cil_path); } rc = sepol_module_package_to_cil(out, mod_pkg); if (rc != 0) { goto exit; } exit: if (in != NULL) { fclose(in); } if (out != NULL) { fclose(out); } sepol_module_package_free(mod_pkg); return rc; } policycoreutils/load_policy/0040755 0000000 0000000 00000000000 13756670066 015357 5ustar000000000 0000000 policycoreutils/load_policy/Makefile0100644 0000000 0000000 00000001774 13756670066 017025 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr SBINDIR ?= $(PREFIX)/sbin MANDIR ?= $(PREFIX)/share/man LOCALEDIR ?= $(DESTDIR)$(PREFIX)/share/locale CFLAGS ?= -Werror -Wall -W override CFLAGS += $(LDFLAGS) -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\"" override LDLIBS += -lsepol -lselinux TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c))) all: $(TARGETS) install: all -mkdir -p $(DESTDIR)$(SBINDIR) install -m 755 $(TARGETS) $(DESTDIR)$(SBINDIR) test -d $(DESTDIR)$(MANDIR)/man8 || install -m 755 -d $(DESTDIR)$(MANDIR)/man8 install -m 644 load_policy.8 $(DESTDIR)$(MANDIR)/man8/ for lang in $(LINGUAS) ; do \ if [ -e $${lang} ] ; then \ test -d $(DESTDIR)$(MANDIR)/$${lang}/man8 || install -m 755 -d $(DESTDIR)$(MANDIR)/$${lang}/man8 ; \ install -m 644 $${lang}/*.8 $(DESTDIR)$(MANDIR)/$${lang}/man8/ ; \ fi ; \ done clean: -rm -f $(TARGETS) *.o indent: ../../scripts/Lindent $(wildcard *.[ch]) relabel: /sbin/restorecon $(DESTDIR)$(SBINDIR)/load_policy policycoreutils/load_policy/load_policy.80100644 0000000 0000000 00000001626 13756670066 017750 0ustar000000000 0000000 .TH LOAD_POLICY "8" "May 2003" "Security Enhanced Linux" NSA .SH NAME load_policy \- load a new SELinux policy into the kernel .SH SYNOPSIS .B load_policy [\-qi] .br .SH DESCRIPTION .PP load_policy loads the installed policy file into the kernel. The existing policy boolean values are automatically preserved across policy reloads rather than being reset to the default values in the policy file. .SH "OPTIONS" .TP .B \-q suppress warning messages. .TP .B \-i initial policy load. Only use this if this is the first time policy is being loaded since boot (usually called from initramfs). .SH "EXIT STATUS" .TP .B 0 Success .TP .B 1 Invalid option .TP .B 2 Policy load failed .TP .B 3 Initial policy load failed and enforcing mode requested .SH SEE ALSO .BR booleans (8) .SH AUTHORS .nf This manual page was written by Dan Walsh . The program was written by Stephen Smalley . policycoreutils/load_policy/load_policy.c0100644 0000000 0000000 00000004060 13756670066 020016 0ustar000000000 0000000 #include #include #include #include #include #include #include #include #ifdef USE_NLS #include /* for setlocale() */ #include /* for gettext() */ #define _(msgid) gettext (msgid) #else #define _(msgid) (msgid) #endif #ifndef PACKAGE #define PACKAGE "policycoreutils" /* the name of this package lang translation */ #endif static __attribute__((__noreturn__)) void usage(const char *progname) { fprintf(stderr, _("usage: %s [-qi]\n"), progname); exit(1); } int main(int argc, char **argv) { int ret, opt, quiet = 0, nargs, init=0, enforce=0; #ifdef USE_NLS setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif while ((opt = getopt(argc, argv, "bqi")) > 0) { switch (opt) { case 'b': fprintf(stderr, "%s: Warning! The -b option is no longer supported, booleans are always preserved across reloads. Continuing...\n", argv[0]); break; case 'q': quiet = 1; sepol_debug(0); break; case 'i': init = 1; break; default: usage(argv[0]); } } nargs = argc - optind; if (nargs > 2) usage(argv[0]); if (nargs >= 1 && !quiet) { fprintf(stderr, "%s: Warning! Policy file argument (%s) is no longer supported, installed policy is always loaded. Continuing...\n", argv[0], argv[optind++]); } if (nargs == 2 && ! quiet) { fprintf(stderr, "%s: Warning! Boolean file argument (%s) is no longer supported, installed booleans file is always used. Continuing...\n", argv[0], argv[optind++]); } if (init) { ret = selinux_init_load_policy(&enforce); if (ret != 0 ) { if (enforce > 0) { /* SELinux in enforcing mode but load_policy failed */ fprintf(stderr, _("%s: Can't load policy and enforcing mode requested: %s\n"), argv[0], strerror(errno)); exit(3); } } } else { ret = selinux_mkload_policy(1); } if (ret < 0) { fprintf(stderr, _("%s: Can't load policy: %s\n"), argv[0], strerror(errno)); exit(2); } exit(0); } policycoreutils/load_policy/ru/0040755 0000000 0000000 00000000000 13756670066 016005 5ustar000000000 0000000 policycoreutils/load_policy/ru/load_policy.80100644 0000000 0000000 00000003352 13756670066 020374 0ustar000000000 0000000 .TH LOAD_POLICY "8" "Май 2003" "Security Enhanced Linux" NSA .SH ИМЯ load_policy \- загрузить новую политику SELinux в ядро .SH ОБЗОР .B load_policy [\-qi] .br .SH ОПИСАНИЕ .PP load_policy загружает установленный файл политики в ядро. Существующие значения логических переключателей политики автоматически сохраняются при перезагрузках политики, а не сбрасываются на установленные в файле политики значения по умолчанию. .SH "ПАРАМЕТРЫ" .TP .B \-q Отменить предупредительные сообщения. .TP .B \-i Начальная загрузка политики. Следует использовать, только если политика загружается впервые с момента запуска (обычно вызывается из initramfs). .SH "СОСТОЯНИЕ ВЫХОДА" .TP .B 0 Успешно .TP .B 1 Недействительный параметр .TP .B 2 Не удалось загрузить политику .TP .B 3 Не удалось выполнить начальную загрузку политики, запрошен принудительный режим .SH СМОТРИТЕ ТАКЖЕ .BR booleans (8) .SH АВТОРЫ .nf Эта страница руководства была написана Dan Walsh . Программа была написана Stephen Smalley . Перевод на русский язык выполнила Герасименко Олеся . policycoreutils/man/0040755 0000000 0000000 00000000000 13756670066 013634 5ustar000000000 0000000 policycoreutils/man/Makefile0100644 0000000 0000000 00000000661 13756670066 015274 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN5DIR ?= $(MANDIR)/man5 all: clean: install: all mkdir -p $(DESTDIR)$(MAN5DIR) install -m 644 man5/*.5 $(DESTDIR)$(MAN5DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man5 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/man5 ; \ install -m 644 $${lang}/man5/*.5 $(DESTDIR)$(MANDIR)/$${lang}/man5 ; \ fi ; \ done relabel: policycoreutils/man/man5/0040755 0000000 0000000 00000000000 13756670066 014474 5ustar000000000 0000000 policycoreutils/man/man5/selinux_config.50100644 0000000 0000000 00000012625 13756670066 017601 0ustar000000000 0000000 .TH "selinux_config" "5" "18 Nov 2011" "Security Enhanced Linux" "SELinux configuration file" .SH "NAME" config \- The SELinux sub-system configuration file. .SH "DESCRIPTION" The SELinux \fIconfig\fR file controls the state of SELinux regarding: .RS .IP "1." 4 The policy enforcement status \- \fIenforcing\fR, \fIpermissive\fR or \fIdisabled\fR. .IP "2." 4 The policy name or type that forms a path to the policy to be loaded and its supporting configuration files. .IP "3." 4 How local users and booleans will be managed when the policy is loaded (note that this function was used by older releases of SELinux and is now deprecated). .IP "4." 4 How SELinux-aware login applications should behave if no valid SELinux users are configured. .IP "5." 4 Whether the system is to be relabeled or not. .RE The entries controlling these functions are described in the \fBFILE FORMAT\fR section. .sp The fully qualified path name of the SELinux configuration file is \fI/etc/selinux/config\fR. .sp If the \fIconfig\fR file is missing or corrupt, then no SELinux policy is loaded (i.e. SELinux is disabled). .sp The \fBsestatus\fR (8) command and the libselinux function \fBselinux_path\fR (3) will return the location of the \fIconfig\fR file. .SH "FILE FORMAT" The \fIconfig\fR file supports the following parameters: .sp .RS \fBSELINUX = \fIenforcing\fR | \fIpermissive\fR | \fIdisabled\fR .br \fBSELINUXTYPE = \fIpolicy_name\fR .br \fBSETLOCALDEFS = \fI0\fR | \fI1\fR .br \fBREQUIREUSERS = \fI0\fR | \fI1\fR .br \fBAUTORELABEL = \fI0\fR | \fI1\fR .RE .sp Where: .br .B SELINUX .RS This entry can contain one of three values: .RS .IP \fIenforcing\fR 4 SELinux security policy is enforced. .IP \fIpermissive\fR 4 SELinux security policy is not enforced but logs the warnings (i.e. the action is allowed to proceed). .IP \fIdisabled\fR SELinux is disabled and no policy is loaded. .RE .sp The entry can be determined using the \fBsestatus\fR(8) command or \fBselinux_getenforcemode\fR(3). .RE .sp .B SELINUXTYPE .RS The \fIpolicy_name\fR entry is used to identify the policy type, and becomes the directory name of where the policy and its configuration files are located. .sp The entry can be determined using the \fBsestatus\fR(8) command or \fBselinux_getpolicytype\fR(3). .sp The \fIpolicy_name\fR is relative to a path that is defined within the SELinux subsystem that can be retrieved by using \fBselinux_path\fR(3). An example entry retrieved by \fBselinux_path\fR(3) is: .br .RS .I /etc/selinux/ .RE .sp The \fIpolicy_name\fR is then appended to this and becomes the 'policy root' location that can be retrieved by \fBselinux_policy_root_path\fR(3). An example entry retrieved is: .RS .I /etc/selinux/targeted .RE .sp The actual binary policy is located relative to this directory and also has a policy name pre-allocated. This information can be retrieved using \fBselinux_binary_policy_path\fR(3). An example entry retrieved by \fBselinux_binary_policy_path\fR(3) is: .br .RS .I /etc/selinux/targeted/policy/policy .RE .sp The binary policy name has by convention the SELinux policy version that it supports appended to it. The maximum policy version supported by the kernel can be determined using the \fBsestatus\fR(8) command or \fBsecurity_policyvers\fR(3). An example binary policy file with the version is: .br .RS .I /etc/selinux/targeted/policy/policy.24 .RE .RE .sp .B SETLOCALDEFS .RS This entry is deprecated and should be removed or set to \fI0\fR. .sp If set to \fI1\fR, then \fBselinux_mkload_policy\fR(3) will read the local customization for booleans (see \fBbooleans\fR(5)) and users (see \fBlocal.users\fR(5)). .RE .sp .B REQUIRESEUSERS .RS This optional entry can be used to fail a login if there is no matching or default entry in the .BR seusers "(5) file or if the " seusers " file is missing. " .sp It is checked by \fBgetseuserbyname\fR(3) that is called by SELinux-aware login applications such as \fBPAM\fR(8). .sp If set to \fI0\fR or the entry missing: .RS .BR getseuserbyname "(3) will return the GNU / Linux user name as the SELinux user." .RE .sp If set to \fI1\fR: .RS .BR getseuserbyname "(3) will fail." .RE .sp The \fBgetseuserbyname\fR(3) man page should be consulted for its use. The format of the \fIseusers\fR file is shown in \fBseusers\fR(5). .sp .RE .sp .B AUTORELABEL .RS This is an optional entry that allows the file system to be relabeled. .sp If set to \fI0\fR and there is a file called \fI.autorelabel\fR in the root directory, then on a reboot, the loader will drop to a shell where a root login is required. An administrator can then manually relabel the file system. .sp If set to \fI1\fR or no entry present (the default) and there is a \fI.autorelabel\fR file in the root directory, then the file system will be automatically relabeled using \fBfixfiles \-F restore\fR .sp In both cases the \fI/.autorelabel\fR file will be removed so that relabeling is not done again. .RE .sp .SH "EXAMPLE" This example \fIconfig\fR file shows the minimum contents for a system to run SELinux in enforcing mode, with a \fIpolicy_name\fR of 'targeted': .sp .RS SELINUX = enforcing .br SELINUXTYPE = targeted .RE .SH "SEE ALSO" .BR selinux "(8), " sestatus "(8), " selinux_path "(3), " selinux_policy_root_path "(3), " selinux_binary_policy_path "(3), " getseuserbyname "(3), " PAM "(8), " fixfiles "(8), " selinux_mkload_policy "(3), " selinux_getpolicytype "(3), " security_policyvers "(3), " selinux_getenforcemode "(3), " seusers "(5), " booleans "(5), " local.users "(5) " policycoreutils/man/ru/0040755 0000000 0000000 00000000000 13756670066 014262 5ustar000000000 0000000 policycoreutils/man/ru/man5/0040755 0000000 0000000 00000000000 13756670066 015122 5ustar000000000 0000000 policycoreutils/man/ru/man5/selinux_config.50100644 0000000 0000000 00000021731 13756670066 020225 0ustar000000000 0000000 .TH "selinux_config" "5" "18 ноября 2011" "Security Enhanced Linux" "Файл конфигурации SELinux" .SH "ИМЯ" config \- файл конфигурации подсистемы SELinux. .SH "ОПИСАНИЕ" Файл \fIconfig\fR SELinux управляет состоянием SELinux, определяя: .RS .IP "1." 4 Состояние применения политики \- \fIenforcing\fR (принудительный режим), \fIpermissive\fR (разрешительный режим) или \fIdisabled\fR (отключена). .IP "2." 4 Имя политики или тип, формирующий путь к политике, которую следует загрузить, и её вспомогательным файлам конфигурации. .IP "3." 4 Способ управления локальными пользователями и логическими переключателями после загрузки политики (обратите внимание, что эта возможность использовалась в предыдущих версиях SELinux, сейчас она устарела). .IP "4." 4 Поведение поддерживающих SELinux приложений при отсутствии настроенных действительных пользователей SELinux. .IP "5." 4 Следует ли повторно проставлять метки в системе. .RE Описание записей, которые управляют этими возможностями, приводится в разделе \fBФОРМАТ ФАЙЛА\fR. .sp Полный путь к файлу конфигурации SELinux: \fI/etc/selinux/config\fR. .sp Если файл \fIconfig\fR отсутствует или повреждён, политика SELinux не будет загружена (то есть SELinux будет отключён). .sp Команда \fBsestatus\fR (8) и функция libselinux \fBselinux_path\fR (3) возвращают расположение файла \fIconfig\fR. .SH "ФОРМАТ ФАЙЛА" Файл \fIconfig\fR поддерживает следующие параметры: .sp .RS \fBSELINUX = \fIenforcing\fR | \fIpermissive\fR | \fIdisabled\fR .br \fBSELINUXTYPE = \fIpolicy_name\fR .br \fBSETLOCALDEFS = \fI0\fR | \fI1\fR .br \fBREQUIREUSERS = \fI0\fR | \fI1\fR .br \fBAUTORELABEL = \fI0\fR | \fI1\fR .RE .sp Где: .br .B SELINUX .RS Эта запись может содержать одно из трёх значений: .RS .IP \fIenforcing\fR 4 Политика безопасности SELinux применяется. .IP \fIpermissive\fR 4 Политика безопасности SELinux не применяется, но ведётся журналирование предупреждений (то есть действиям разрешено продолжать выполняться). .IP \fIdisabled\fR SELinux отключён, политика не загружена. .RE .sp Значение записи можно узнать с помощью команды \fBsestatus\fR(8) или \fBselinux_getenforcemode\fR(3). .RE .sp .B SELINUXTYPE .RS Запись \fIpolicy_name\fR используется для идентификации типа политики и становится именем каталога, в котором располагаются политика и её файлы конфигурации. .sp Значение записи можно узнать с помощью команды \fBsestatus\fR(8) или \fBselinux_getpolicytype\fR(3). .sp \fIpolicy_name\fR относится к пути, который определён внутри подсистемы SELinux и может быть получен с помощью \fBselinux_path\fR(3). Пример записи, полученной с помощью \fBselinux_path\fR(3): .br .RS .I /etc/selinux/ .RE .sp Затем к концу этой записи добавляется \fIpolicy_name\fR, и она становится корневым расположением политики, которое может быть получено с помощью \fBselinux_policy_root_path\fR(3). Пример полученной записи: .RS .I /etc/selinux/targeted .RE .sp Фактическая двоичная политика расположена относительно этого каталога и также имеет предварительно выделенное имя политики. Эту информацию можно получить с помощью \fBselinux_binary_policy_path\fR(3). Пример записи, полученной с помощью \fBselinux_binary_policy_path\fR(3): .br .RS .I /etc/selinux/targeted/policy/policy .RE .sp По соглашению к концу имени двоичной политики добавляется версия политики SELinux, которую она поддерживает. Максимальную версию политики, поддерживаемую ядром, можно определить с помощью команды \fBsestatus\fR(8) или \fBsecurity_policyvers\fR(3). Пример файла двоичной политики с версией: .br .RS .I /etc/selinux/targeted/policy/policy.24 .RE .RE .sp .B SETLOCALDEFS .RS Эта запись устарела. Следует её удалить или задать для неё значение \fI0\fR. .sp Если задано значение \fI1\fR, \fBselinux_mkload_policy\fR(3) выполнит чтение логических переключателей (см. \fBbooleans\fR(5)) и пользователей (см. \fBlocal.users\fR(5)) в локальной настройке. .RE .sp .B REQUIRESEUSERS .RS Эта необязательная запись позволяет сделать попытку входа неудачной, если в файле .BR seusers "(5) нет соответствующей записи или записи по умолчанию или отсутствует сам файл " seusers ". " .sp Она проверяется функцией \fBgetseuserbyname\fR(3), которая вызывается поддерживающими SELinux приложениями для входа, например, \fBPAM\fR(8). .sp Если задано значение \fI0\fR или отсутствует запись: .RS .BR getseuserbyname "(3) вернёт имя пользователя GNU / Linux в качестве пользователя SELinux." .RE .sp Если задано значение \fI1\fR: .RS .BR getseuserbyname "(3) не удастся выполнить." .RE .sp Описание работы \fBgetseuserbyname\fR(3) содержится на соответствующей man-странице. Формат файла \fIseusers\fR показан в \fBseusers\fR(5). .sp .RE .sp .B AUTORELABEL .RS Эта необязательная запись позволяет повторно проставлять метки в файловой системе. .sp Если задано значение \fI0\fR и в корневом каталоге имеется файл с именем \fI.autorelabel\fR, при перезагрузке загрузчик перейдёт в оболочку, запрашивающую вход в качестве пользователя root. Затем администратор сможет вручную проставить метки в файловой системе. .sp Если задано значение \fI1\fR или запись отсутствует (состояние по умолчанию) и в корневом каталоге имеется файл \fI.autorelabel\fR, в файловой системе с помощью \fBfixfiles \-F restore\fR будут автоматически повторно проставлены метки. .sp В обоих случаях файл \fI/.autorelabel\fR будет удалён, чтобы предотвратить последующее повторное проставление меток. .RE .sp .SH "ПРИМЕР" В этом примере показано минимальное содержимое файла \fIconfig\fR, которое обеспечит запуск SELinux в системе в принудительном режиме, со значением \fIpolicy_name\fR 'targeted': .sp .RS SELINUX = enforcing .br SELINUXTYPE = targeted .RE .SH "СМОТРИТЕ ТАКЖЕ" .BR selinux "(8), " sestatus "(8), " selinux_path "(3), " selinux_policy_root_path "(3), " selinux_binary_policy_path "(3), " getseuserbyname "(3), " PAM "(8), " fixfiles "(8), " selinux_mkload_policy "(3), " selinux_getpolicytype "(3), " security_policyvers "(3), " selinux_getenforcemode "(3), " seusers "(5), " booleans "(5), " local.users "(5) " .SH АВТОРЫ Перевод на русский язык выполнила Герасименко Олеся . policycoreutils/newrole/0040755 0000000 0000000 00000000000 13756670066 014534 5ustar000000000 0000000 policycoreutils/newrole/Makefile0100644 0000000 0000000 00000005373 13756670066 016201 0ustar000000000 0000000 # Installation directories. LINGUAS ?= ru PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/share/man ETCDIR ?= /etc LOCALEDIR = $(DESTDIR)$(PREFIX)/share/locale PAMH ?= $(shell test -f /usr/include/security/pam_appl.h && echo y) AUDITH ?= $(shell test -f /usr/include/libaudit.h && echo y) # Enable capabilities to permit newrole to generate audit records. # This will make newrole a setuid root program. # The capabilities used are: CAP_AUDIT_WRITE. AUDIT_LOG_PRIV ?= n # Enable capabilities to permit newrole to utilitize the pam_namespace module. # This will make newrole a setuid root program. # The capabilities used are: CAP_SYS_ADMIN, CAP_CHOWN, CAP_FOWNER and # CAP_DAC_OVERRIDE. NAMESPACE_PRIV ?= n # If LSPP_PRIV is y, then newrole will be made into setuid root program. # Enabling this option will force AUDIT_LOG_PRIV and NAMESPACE_PRIV to be y. LSPP_PRIV ?= n VERSION = $(shell cat ../VERSION) CFLAGS ?= -Werror -Wall -W EXTRA_OBJS = override CFLAGS += -DVERSION=\"$(VERSION)\" -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\"" override LDLIBS += -lselinux ifeq ($(PAMH), y) override CFLAGS += -DUSE_PAM EXTRA_OBJS += hashtab.o override LDLIBS += -lpam -lpam_misc else override CFLAGS += -D_XOPEN_SOURCE=500 override LDLIBS += -lcrypt endif ifeq ($(AUDITH), y) override CFLAGS += -DUSE_AUDIT override LDLIBS += -laudit endif ifeq ($(LSPP_PRIV),y) override AUDIT_LOG_PRIV=y override NAMESPACE_PRIV=y endif ifeq ($(AUDIT_LOG_PRIV),y) override CFLAGS += -DAUDIT_LOG_PRIV IS_SUID=y endif ifeq ($(NAMESPACE_PRIV),y) override CFLAGS += -DNAMESPACE_PRIV IS_SUID=y endif ifeq ($(IS_SUID),y) MODE := 4555 override LDLIBS += -lcap-ng else MODE := 0555 endif all: newrole newrole: newrole.o $(EXTRA_OBJS) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) install: all test -d $(DESTDIR)$(BINDIR) || install -m 755 -d $(DESTDIR)$(BINDIR) test -d $(DESTDIR)$(ETCDIR)/pam.d || install -m 755 -d $(DESTDIR)$(ETCDIR)/pam.d test -d $(DESTDIR)$(MANDIR)/man1 || install -m 755 -d $(DESTDIR)$(MANDIR)/man1 install -m $(MODE) newrole $(DESTDIR)$(BINDIR) install -m 644 newrole.1 $(DESTDIR)$(MANDIR)/man1/ for lang in $(LINGUAS) ; do \ if [ -e $${lang} ] ; then \ test -d $(DESTDIR)$(MANDIR)/$${lang}/man1 || install -m 755 -d $(DESTDIR)$(MANDIR)/$${lang}/man1 ; \ install -m 644 $${lang}/*.1 $(DESTDIR)$(MANDIR)/$${lang}/man1/ ; \ fi ; \ done ifeq ($(PAMH), y) test -d $(DESTDIR)$(ETCDIR)/pam.d || install -m 755 -d $(DESTDIR)$(ETCDIR)/pam.d ifeq ($(LSPP_PRIV),y) install -m 644 newrole-lspp.pamd $(DESTDIR)$(ETCDIR)/pam.d/newrole else install -m 644 newrole.pamd $(DESTDIR)$(ETCDIR)/pam.d/newrole endif endif clean: rm -f newrole *.o indent: ../../scripts/Lindent $(wildcard *.[ch]) relabel: install /sbin/restorecon $(DESTDIR)$(BINDIR)/newrole policycoreutils/newrole/hashtab.c0100644 0000000 0000000 00000013021 13756670066 016304 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the hash table type. */ #include #include #include "hashtab.h" hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size) { hashtab_t p; unsigned int i; p = (hashtab_t) malloc(sizeof(hashtab_val_t)); if (p == NULL) return p; memset(p, 0, sizeof(hashtab_val_t)); p->size = size; p->nel = 0; p->hash_value = hash_value; p->keycmp = keycmp; p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size); if (p->htable == NULL) { free(p); return NULL; } for (i = 0; i < size; i++) p->htable[i] = (hashtab_ptr_t) NULL; return p; } int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) { int hvalue; hashtab_ptr_t prev, cur, newnode; if (!h) return HASHTAB_OVERFLOW; hvalue = h->hash_value(h, key); prev = NULL; cur = h->htable[hvalue]; while (cur && h->keycmp(h, key, cur->key) > 0) { prev = cur; cur = cur->next; } if (cur && (h->keycmp(h, key, cur->key) == 0)) return HASHTAB_PRESENT; newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) return HASHTAB_OVERFLOW; memset(newnode, 0, sizeof(struct hashtab_node)); newnode->key = key; newnode->datum = datum; if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } h->nel++; return HASHTAB_SUCCESS; } int hashtab_remove(hashtab_t h, hashtab_key_t key, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { int hvalue; hashtab_ptr_t cur, last; if (!h) return HASHTAB_MISSING; hvalue = h->hash_value(h, key); last = NULL; cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { last = cur; cur = cur->next; } if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) return HASHTAB_MISSING; if (last == NULL) h->htable[hvalue] = cur->next; else last->next = cur->next; if (destroy) destroy(cur->key, cur->datum, args); free(cur); h->nel--; return HASHTAB_SUCCESS; } int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { int hvalue; hashtab_ptr_t prev, cur, newnode; if (!h) return HASHTAB_OVERFLOW; hvalue = h->hash_value(h, key); prev = NULL; cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { prev = cur; cur = cur->next; } if (cur && (h->keycmp(h, key, cur->key) == 0)) { if (destroy) destroy(cur->key, cur->datum, args); cur->key = key; cur->datum = datum; } else { newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) return HASHTAB_OVERFLOW; memset(newnode, 0, sizeof(struct hashtab_node)); newnode->key = key; newnode->datum = datum; if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } } return HASHTAB_SUCCESS; } hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) { int hvalue; hashtab_ptr_t cur; if (!h) return NULL; hvalue = h->hash_value(h, key); cur = h->htable[hvalue]; while (cur != NULL && h->keycmp(h, key, cur->key) > 0) cur = cur->next; if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) return NULL; return cur->datum; } void hashtab_destroy(hashtab_t h) { unsigned int i; hashtab_ptr_t cur, temp; if (!h) return; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; free(temp); } h->htable[i] = NULL; } free(h->htable); h->htable = NULL; free(h); } int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int i, ret; hashtab_ptr_t cur; if (!h) return HASHTAB_SUCCESS; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { ret = apply(cur->key, cur->datum, args); if (ret) return ret; cur = cur->next; } } return HASHTAB_SUCCESS; } void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int i; int ret; hashtab_ptr_t last, cur, temp; if (!h) return; for (i = 0; i < h->size; i++) { last = NULL; cur = h->htable[i]; while (cur != NULL) { ret = apply(cur->key, cur->datum, args); if (ret) { if (last) { last->next = cur->next; } else { h->htable[i] = cur->next; } temp = cur; cur = cur->next; if (destroy) destroy(temp->key, temp->datum, args); free(temp); h->nel--; } else { last = cur; cur = cur->next; } } } return; } void hashtab_hash_eval(hashtab_t h, char *tag) { unsigned int i; int chain_len, slots_used, max_chain_len; hashtab_ptr_t cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < h->size; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, h->size, max_chain_len); } policycoreutils/newrole/hashtab.h0100644 0000000 0000000 00000010655 13756670066 016323 0ustar000000000 0000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A hash table (hashtab) maintains associations between * key values and datum values. The type of the key values * and the type of the datum values is arbitrary. The * functions for hash computation and key comparison are * provided by the creator of the table. */ #ifndef _NEWROLE_HASHTAB_H_ #define _NEWROLE_HASHTAB_H_ #include #include #include typedef char *hashtab_key_t; /* generic key type */ typedef const char *const_hashtab_key_t; /* constant generic key type */ typedef void *hashtab_datum_t; /* generic datum type */ typedef struct hashtab_node *hashtab_ptr_t; typedef struct hashtab_node { hashtab_key_t key; hashtab_datum_t datum; hashtab_ptr_t next; } hashtab_node_t; typedef struct hashtab_val { hashtab_ptr_t *htable; /* hash table */ unsigned int size; /* number of slots in hash table */ uint32_t nel; /* number of elements in hash table */ unsigned int (*hash_value) (struct hashtab_val * h, const_hashtab_key_t key); /* hash function */ int (*keycmp) (struct hashtab_val * h, const_hashtab_key_t key1, const_hashtab_key_t key2); /* key comparison function */ } hashtab_val_t; typedef hashtab_val_t *hashtab_t; /* Define status codes for hash table functions */ #define HASHTAB_SUCCESS 0 #define HASHTAB_OVERFLOW -ENOMEM #define HASHTAB_PRESENT -EEXIST #define HASHTAB_MISSING -ENOENT /* Creates a new hash table with the specified characteristics. Returns NULL if insufficent space is available or the new hash table otherwise. */ extern hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size); /* Inserts the specified (key, datum) pair into the specified hash table. Returns HASHTAB_OVERFLOW if insufficient space is available or HASHTAB_PRESENT if there is already an entry with the same key or HASHTAB_SUCCESS otherwise. */ extern int hashtab_insert(hashtab_t h, hashtab_key_t k, hashtab_datum_t d); /* Removes the entry with the specified key from the hash table. Applies the specified destroy function to (key,datum,args) for the entry. Returns HASHTAB_MISSING if no entry has the specified key or HASHTAB_SUCCESS otherwise. */ extern int hashtab_remove(hashtab_t h, hashtab_key_t k, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Insert or replace the specified (key, datum) pair in the specified hash table. If an entry for the specified key already exists, then the specified destroy function is applied to (key,datum,args) for the entry prior to replacing the entry's contents. Returns HASHTAB_OVERFLOW if insufficient space is available or HASHTAB_SUCCESS otherwise. */ extern int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Searches for the entry with the specified key in the hash table. Returns NULL if no entry has the specified key or the datum of the entry otherwise. */ extern hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t k); /* Destroys the specified hash table. */ extern void hashtab_destroy(hashtab_t h); /* Applies the specified apply function to (key,datum,args) for each entry in the specified hash table. The order in which the function is applied to the entries is dependent upon the internal structure of the hash table. If apply returns a non-zero status, then hashtab_map will cease iterating through the hash table and will propagate the error return to its caller. */ extern int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Same as hashtab_map, except that if apply returns a non-zero status, then the (key,datum) pair will be removed from the hashtab and the destroy function will be applied to (key,datum,args). */ extern void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); extern void hashtab_hash_eval(hashtab_t h, char *tag); #endif policycoreutils/newrole/newrole-lspp.pamd0100644 0000000 0000000 00000000254 13756670066 020024 0ustar000000000 0000000 #%PAM-1.0 auth include system-auth account include system-auth password include system-auth session required pam_namespace.so unmnt_remnt no_unmount_on_close policycoreutils/newrole/newrole.10100644 0000000 0000000 00000006341 13756670066 016272 0ustar000000000 0000000 .TH NEWROLE "1" "October 2000" "Security Enhanced Linux" NSA .SH NAME newrole \- run a shell with a new SELinux role .SH SYNOPSIS .B newrole [\fB-r\fR|\fB--role\fR] \fIROLE\fR [\fB-t\fR|\fB--type\fR] \fITYPE\fR [\fB-l\fR|\fB--level\fR] [\fB-p\fR|\fB--preserve-environment\fR] \fILEVEL\fR [-- [\fIARGS\fR]...] .SH DESCRIPTION .PP Run a new shell in a new context. The new context is derived from the old context in which .B newrole is originally executed. If the .B -r or .B --role option is specified, then the new context will have the role specified by \fIROLE\fR. If the .B -t or .B --type option is specified, then the new context will have the type (domain) specified by \fITYPE\fR. If a role is specified, but no type is specified, the default type is derived from the specified role. If the .B -l or .B --level option is specified, then the new context will have the sensitivity level specified by \fILEVEL\fR. If \fILEVEL\fR is a range, the new context will have the sensitivity level and clearance specified by that range. If the .B -p or .B --preserve-environment option is specified, the shell with the new SELinux context will preserve environment variables, otherwise a new minimal environment is created. .PP Additional arguments .I ARGS may be provided after a -- option, in which case they are supplied to the new shell. In particular, an argument of \-\- \-c will cause the next argument to be treated as a command by most command interpreters. .PP If a command argument is specified to newrole and the command name is found in /etc/selinux/newrole_pam.conf, then the pam service name listed in that file for the command will be used rather than the normal newrole pam configuration. This allows for per-command pam configuration when invoked via newrole, e.g. to skip the interactive re-authentication phase. .PP The new shell will be the shell specified in the user's entry in the .I /etc/passwd file. .PP The .B -V or .B --version shows the current version of newrole .PP .SH EXAMPLE .br Changing role: # id \-Z staff_u:staff_r:staff_t:SystemLow-SystemHigh # newrole \-r sysadm_r # id \-Z staff_u:sysadm_r:sysadm_t:SystemLow-SystemHigh Changing sensitivity only: # id \-Z staff_u:sysadm_r:sysadm_t:Unclassified-SystemHigh # newrole \-l Secret # id \-Z staff_u:sysadm_r:sysadm_t:Secret-SystemHigh .PP Changing sensitivity and clearance: # id \-Z staff_u:sysadm_r:sysadm_t:Unclassified-SystemHigh # newrole \-l Secret-Secret # id \-Z staff_u:sysadm_r:sysadm_t:Secret .PP Running a program in a given role or level: # newrole \-r sysadm_r \-\- \-c "/path/to/app arg1 arg2..." # newrole \-l Secret \-\- \-c "/path/to/app arg1 arg2..." .SH FILES /etc/passwd - user account information .br /etc/shadow - encrypted passwords and age information .br /etc/selinux//contexts/default_type - default types for roles .br /etc/selinux//contexts/securetty_types - securetty types for level changes .br /etc/selinux/newrole_pam.conf - optional mapping of commands to separate pam service names .br .SH SEE ALSO .BR runcon (1) .SH AUTHORS .nf Anthony Colatrella Tim Fraser Steve Grubb Darrel Goeddel Michael Thompson Dan Walsh policycoreutils/newrole/newrole.c0100644 0000000 0000000 00000106054 13756670066 016356 0ustar000000000 0000000 /************************************************************************ * * newrole * * SYNOPSIS: * * This program allows a user to change their SELinux RBAC role and/or * SELinux TE type (domain) in a manner similar to the way the traditional * UNIX su program allows a user to change their identity. * * USAGE: * * newrole [ -r role ] [ -t type ] [ -l level ] [ -V ] [ -- args ] * * BUILD OPTIONS: * * option USE_PAM: * * Set the USE_PAM constant if you want to authenticate users via PAM. * If USE_PAM is not set, users will be authenticated via direct * access to the shadow password file. * * If you decide to use PAM must be told how to handle newrole. A * good rule-of-thumb might be to tell PAM to handle newrole in the * same way it handles su, except that you should remove the pam_rootok.so * entry so that even root must re-authenticate to change roles. * * If you choose not to use PAM, make sure you have a shadow passwd file * in /etc/shadow. You can use a symlink if your shadow passwd file * lives in another directory. Example: * su * cd /etc * ln -s /etc/auth/shadow shadow * * If you decide not to use PAM, you will also have to make newrole * setuid root, so that it can read the shadow passwd file. * * * Authors: * Anthony Colatrella * Tim Fraser * Steve Grubb * Darrel Goeddel * Michael Thompson * Dan Walsh * *************************************************************************/ #define _GNU_SOURCE #if defined(AUDIT_LOG_PRIV) && !defined(USE_AUDIT) #error AUDIT_LOG_PRIV needs the USE_AUDIT option #endif #if defined(NAMESPACE_PRIV) && !defined(USE_PAM) #error NAMESPACE_PRIV needs the USE_PAM option #endif #include #include /* for malloc(), realloc(), free() */ #include /* for getpwuid() */ #include #include /* to make getuid() and getpwuid() happy */ #include /* for wait() */ #include /* for getopt_long() form of getopt() */ #include #include #include #include /* for is_selinux_enabled() */ #include /* for context-mangling functions */ #include #include /* for SELINUX_DEFAULTUSER */ #include #include /* for getuid(), exit(), getopt() */ #ifdef USE_AUDIT #include #endif #if defined(AUDIT_LOG_PRIV) || defined(NAMESPACE_PRIV) #include #include #endif #ifdef USE_NLS #include /* for setlocale() */ #include /* for gettext() */ #define _(msgid) gettext (msgid) #else #define _(msgid) (msgid) #endif #ifndef PACKAGE #define PACKAGE "policycoreutils" /* the name of this package lang translation */ #endif #define TRUE 1 #define FALSE 0 /* USAGE_STRING describes the command-line args of this program. */ #define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]" #ifdef USE_PAM #define PAM_SERVICE_CONFIG "/etc/selinux/newrole_pam.conf"; #endif #define DEFAULT_PATH "/usr/bin:/bin" #define DEFAULT_CONTEXT_SIZE 255 /* first guess at context size */ extern char **environ; /** * Construct from the current range and specified desired level a resulting * range. If the specified level is a range, return that. If it is not, then * construct a range with level as the sensitivity and clearance of the current * context. * * newlevel - the level specified on the command line * range - the range in the current context * * Returns malloc'd memory */ static char *build_new_range(char *newlevel, const char *range) { char *newrangep = NULL; const char *tmpptr; size_t len; /* a missing or empty string */ if (!range || !strlen(range) || !newlevel || !strlen(newlevel)) return NULL; /* if the newlevel is actually a range - just use that */ if (strchr(newlevel, '-')) { newrangep = strdup(newlevel); return newrangep; } /* look for MLS range in current context */ tmpptr = strchr(range, '-'); if (tmpptr) { /* we are inserting into a ranged MLS context */ len = strlen(newlevel) + 1 + strlen(tmpptr + 1) + 1; newrangep = (char *)malloc(len); if (!newrangep) return NULL; snprintf(newrangep, len, "%s-%s", newlevel, tmpptr + 1); } else { /* we are inserting into a currently non-ranged MLS context */ if (!strcmp(newlevel, range)) { newrangep = strdup(range); } else { len = strlen(newlevel) + 1 + strlen(range) + 1; newrangep = (char *)malloc(len); if (!newrangep) return NULL; snprintf(newrangep, len, "%s-%s", newlevel, range); } } return newrangep; } #ifdef USE_PAM /************************************************************************ * * All PAM code goes in this section. * ************************************************************************/ #include /* for PAM functions */ #include /* for misc_conv PAM utility function */ const char *service_name = "newrole"; /* authenticate_via_pam() * * in: pw - struct containing data from our user's line in * the passwd file. * out: nothing * return: value condition * ----- --------- * 1 PAM thinks that the user authenticated themselves properly * 0 otherwise * * This function uses PAM to authenticate the user running this * program. This is the only function in this program that makes PAM * calls. */ int authenticate_via_pam(const char *ttyn, pam_handle_t * pam_handle) { int result = 0; /* set to 0 (not authenticated) by default */ int pam_rc; /* pam return code */ const char *tty_name; if (ttyn) { if (strncmp(ttyn, "/dev/", 5) == 0) tty_name = ttyn + 5; else tty_name = ttyn; pam_rc = pam_set_item(pam_handle, PAM_TTY, tty_name); if (pam_rc != PAM_SUCCESS) { fprintf(stderr, _("failed to set PAM_TTY\n")); goto out; } } /* Ask PAM to authenticate the user running this program */ pam_rc = pam_authenticate(pam_handle, 0); if (pam_rc != PAM_SUCCESS) { goto out; } /* Ask PAM to verify acct_mgmt */ pam_rc = pam_acct_mgmt(pam_handle, 0); if (pam_rc == PAM_SUCCESS) { result = 1; /* user authenticated OK! */ } out: return result; } /* authenticate_via_pam() */ #include "hashtab.h" static int free_hashtab_entry(hashtab_key_t key, hashtab_datum_t d, void *args __attribute__ ((unused))) { free(key); free(d); return 0; } static unsigned int reqsymhash(hashtab_t h, const_hashtab_key_t key) { char *p, *keyp; size_t size; unsigned int val; val = 0; keyp = (char *)key; size = strlen(keyp); for (p = keyp; ((size_t) (p - keyp)) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (h->size - 1); } static int reqsymcmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { return strcmp(key1, key2); } static hashtab_t app_service_names = NULL; #define PAM_SERVICE_SLOTS 64 static int process_pam_config(FILE * cfg) { const char *config_file_path = PAM_SERVICE_CONFIG; char *line_buf = NULL; unsigned long lineno = 0; size_t len = 0; char *app = NULL; char *service = NULL; int ret; while (getline(&line_buf, &len, cfg) > 0) { char *buffer = line_buf; lineno++; while (isspace(*buffer)) buffer++; if (buffer[0] == '#') continue; if (buffer[0] == '\n' || buffer[0] == '\0') continue; app = service = NULL; ret = sscanf(buffer, "%ms %ms\n", &app, &service); if (ret < 2 || !app || !service) goto err; ret = hashtab_insert(app_service_names, app, service); if (ret == HASHTAB_OVERFLOW) { fprintf(stderr, _ ("newrole: service name configuration hashtable overflow\n")); goto err; } } free(line_buf); return 0; err: free(app); free(service); fprintf(stderr, _("newrole: %s: error on line %lu.\n"), config_file_path, lineno); free(line_buf); return -1; } /* * Read config file ignoring comment lines. * Files specified one per line executable with a corresponding * pam service name. */ static int read_pam_config(void) { const char *config_file_path = PAM_SERVICE_CONFIG; FILE *cfg = NULL; cfg = fopen(config_file_path, "r"); if (!cfg) return 0; /* This configuration is optional. */ app_service_names = hashtab_create(reqsymhash, reqsymcmp, PAM_SERVICE_SLOTS); if (!app_service_names) goto err; if (process_pam_config(cfg)) goto err; fclose(cfg); return 0; err: fclose(cfg); return -1; } #else /* else !USE_PAM */ /************************************************************************ * * All shadow passwd code goes in this section. * ************************************************************************/ #include /* for shadow passwd functions */ #include /* for strlen(), memset() */ #define PASSWORD_PROMPT _("Password:") /* prompt for getpass() */ /* authenticate_via_shadow_passwd() * * in: uname - the calling user's user name * out: nothing * return: value condition * ----- --------- * 1 user authenticated themselves properly according to the * shadow passwd file. * 0 otherwise * * This function uses the shadow passwd file to thenticate the user running * this program. */ int authenticate_via_shadow_passwd(const char *uname) { struct spwd *p_shadow_line; char *unencrypted_password_s; char *encrypted_password_s; setspent(); p_shadow_line = getspnam(uname); endspent(); if (!(p_shadow_line)) { fprintf(stderr, _("Cannot find your entry in the shadow " "passwd file.\n")); return 0; } /* Ask user to input unencrypted password */ if (!(unencrypted_password_s = getpass(PASSWORD_PROMPT))) { fprintf(stderr, _("getpass cannot open /dev/tty\n")); return 0; } /* Use crypt() to encrypt user's input password. */ encrypted_password_s = crypt(unencrypted_password_s, p_shadow_line->sp_pwdp); memset(unencrypted_password_s, 0, strlen(unencrypted_password_s)); return (!strcmp(encrypted_password_s, p_shadow_line->sp_pwdp)); } #endif /* if/else USE_PAM */ /** * This function checks to see if the shell is known in /etc/shells. * If so, it returns 1. On error or illegal shell, it returns 0. */ static int verify_shell(const char *shell_name) { int found = 0; const char *buf; if (!(shell_name && shell_name[0])) return found; while ((buf = getusershell()) != NULL) { /* ignore comments */ if (*buf == '#') continue; /* check the shell skipping newline char */ if (!strcmp(shell_name, buf)) { found = 1; break; } } endusershell(); return found; } /** * Determine the Linux user identity to re-authenticate. * If supported and set, use the login uid, as this should be more stable. * Otherwise, use the real uid. * * This function assigns malloc'd memory into the pw_copy struct. * Returns zero on success, non-zero otherwise */ static int extract_pw_data(struct passwd *pw_copy) { uid_t uid; struct passwd *pw; #ifdef USE_AUDIT uid = audit_getloginuid(); if (uid == (uid_t) - 1) uid = getuid(); #else uid = getuid(); #endif setpwent(); pw = getpwuid(uid); endpwent(); if (!(pw && pw->pw_name && pw->pw_name[0] && pw->pw_shell && pw->pw_shell[0] && pw->pw_dir && pw->pw_dir[0])) { fprintf(stderr, _("cannot find valid entry in the passwd file.\n")); return -1; } *pw_copy = *pw; pw = pw_copy; pw->pw_name = strdup(pw->pw_name); pw->pw_dir = strdup(pw->pw_dir); pw->pw_shell = strdup(pw->pw_shell); if (!(pw->pw_name && pw->pw_dir && pw->pw_shell)) { fprintf(stderr, _("Out of memory!\n")); goto out_free; } if (verify_shell(pw->pw_shell) == 0) { fprintf(stderr, _("Error! Shell is not valid.\n")); goto out_free; } return 0; out_free: free(pw->pw_name); free(pw->pw_dir); free(pw->pw_shell); pw->pw_name = NULL; pw->pw_dir = NULL; pw->pw_shell = NULL; return -1; } /** * Either restore the original environment, or set up a minimal one. * * The minimal environment contains: * TERM, DISPLAY and XAUTHORITY - if they are set, preserve values * HOME, SHELL, USER and LOGNAME - set to contents of /etc/passwd * PATH - set to default value DEFAULT_PATH * * Returns zero on success, non-zero otherwise */ static int restore_environment(int preserve_environment, char **old_environ, const struct passwd *pw) { char const *term_env; char const *display_env; char const *xauthority_env; char *term = NULL; /* temporary container */ char *display = NULL; /* temporary container */ char *xauthority = NULL; /* temporary container */ int rc; environ = old_environ; if (preserve_environment) return 0; term_env = getenv("TERM"); display_env = getenv("DISPLAY"); xauthority_env = getenv("XAUTHORITY"); /* Save the variable values we want */ if (term_env) term = strdup(term_env); if (display_env) display = strdup(display_env); if (xauthority_env) xauthority = strdup(xauthority_env); if ((term_env && !term) || (display_env && !display) || (xauthority_env && !xauthority)) { rc = -1; goto out; } /* Construct a new environment */ if ((rc = clearenv())) { fprintf(stderr, _("Unable to clear environment\n")); goto out; } /* Restore that which we saved */ if (term) rc |= setenv("TERM", term, 1); if (display) rc |= setenv("DISPLAY", display, 1); if (xauthority) rc |= setenv("XAUTHORITY", xauthority, 1); rc |= setenv("HOME", pw->pw_dir, 1); rc |= setenv("SHELL", pw->pw_shell, 1); rc |= setenv("USER", pw->pw_name, 1); rc |= setenv("LOGNAME", pw->pw_name, 1); rc |= setenv("PATH", DEFAULT_PATH, 1); out: free(term); free(display); free(xauthority); return rc; } /** * This function will drop the capabilities so that we are left * only with access to the audit system. If the user is root, we leave * the capabilities alone since they already should have access to the * audit netlink socket. * * Returns zero on success, non-zero otherwise */ #if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV) static int drop_capabilities(int full) { uid_t uid = getuid(); if (!uid) return 0; capng_setpid(getpid()); capng_clear(CAPNG_SELECT_CAPS); if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); return -1; } /* Change uid */ if (setresuid(uid, uid, uid)) { fprintf(stderr, _("Error changing uid, aborting.\n")); return -1; } if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); return -1; } if (! full) capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_AUDIT_WRITE); return capng_apply(CAPNG_SELECT_CAPS); } #elif defined(NAMESPACE_PRIV) /** * This function will drop the capabilities so that we are left * only with access to the audit system and the ability to raise * CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_FOWNER and CAP_CHOWN, * before invoking pam_namespace. These capabilities are needed * for performing bind mounts/unmounts and to create potential new * instance directories with appropriate DAC attributes. If the * user is root, we leave the capabilities alone since they already * should have access to the audit netlink socket and should have * the ability to create/mount/unmount instance directories. * * Returns zero on success, non-zero otherwise */ static int drop_capabilities(int full) { uid_t uid = getuid(); if (!uid) return 0; capng_setpid(getpid()); capng_clear(CAPNG_SELECT_CAPS); if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); return -1; } /* Change uid */ if (setresuid(uid, uid, uid)) { fprintf(stderr, _("Error changing uid, aborting.\n")); return -1; } if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); return -1; } if (! full) capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_SYS_ADMIN , CAP_FOWNER , CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_AUDIT_WRITE, -1); return capng_apply(CAPNG_SELECT_CAPS); } #else static inline int drop_capabilities(__attribute__ ((__unused__)) int full) { return 0; } #endif #ifdef NAMESPACE_PRIV /** * This function will set the uid values to be that of caller's uid, and * will drop any privilages which maybe have been raised. */ static int transition_to_caller_uid() { uid_t uid = getuid(); if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); return -1; } if (setresuid(uid, uid, uid)) { fprintf(stderr, _("Error changing uid, aborting.\n")); return -1; } return 0; } #endif #ifdef AUDIT_LOG_PRIV /* Send audit message */ static int send_audit_message(int success, security_context_t old_context, security_context_t new_context, const char *ttyn) { char *msg = NULL; int rc; int audit_fd = audit_open(); if (audit_fd < 0) { fprintf(stderr, _("Error connecting to audit system.\n")); return -1; } if (asprintf(&msg, "newrole: old-context=%s new-context=%s", old_context ? old_context : "?", new_context ? new_context : "?") < 0) { fprintf(stderr, _("Error allocating memory.\n")); rc = -1; goto out; } rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, msg, NULL, NULL, ttyn, success); if (rc <= 0) { fprintf(stderr, _("Error sending audit message.\n")); rc = -1; goto out; } rc = 0; out: free(msg); close(audit_fd); return rc; } #else static inline int send_audit_message(int success __attribute__ ((unused)), security_context_t old_context __attribute__ ((unused)), security_context_t new_context __attribute__ ((unused)), const char *ttyn __attribute__ ((unused))) { return 0; } #endif /** * This function attempts to relabel the tty. If this function fails, then * the fd is closed, the contexts are free'd and -1 is returned. On success, * a valid fd is returned and tty_context and new_tty_context are set. * * This function will not fail if it can not relabel the tty when selinux is * in permissive mode. */ static int relabel_tty(const char *ttyn, security_context_t new_context, security_context_t * tty_context, security_context_t * new_tty_context) { int fd, rc; int enforcing = security_getenforce(); security_context_t tty_con = NULL; security_context_t new_tty_con = NULL; if (!ttyn) return 0; if (enforcing < 0) { fprintf(stderr, _("Could not determine enforcing mode.\n")); return -1; } /* Re-open TTY descriptor */ fd = open(ttyn, O_RDWR | O_NONBLOCK); if (fd < 0) { fprintf(stderr, _("Error! Could not open %s.\n"), ttyn); return fd; } /* this craziness is to make sure we cann't block on open and deadlock */ rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); if (rc) { fprintf(stderr, _("Error! Could not clear O_NONBLOCK on %s\n"), ttyn); close(fd); return rc; } if (fgetfilecon(fd, &tty_con) < 0) { fprintf(stderr, _("%s! Could not get current context " "for %s, not relabeling tty.\n"), enforcing ? "Error" : "Warning", ttyn); if (enforcing) goto close_fd; } if (tty_con && (security_compute_relabel(new_context, tty_con, string_to_security_class("chr_file"), &new_tty_con) < 0)) { fprintf(stderr, _("%s! Could not get new context for %s, " "not relabeling tty.\n"), enforcing ? "Error" : "Warning", ttyn); if (enforcing) goto close_fd; } if (new_tty_con) if (fsetfilecon(fd, new_tty_con) < 0) { fprintf(stderr, _("%s! Could not set new context for %s\n"), enforcing ? "Error" : "Warning", ttyn); freecon(new_tty_con); new_tty_con = NULL; if (enforcing) goto close_fd; } *tty_context = tty_con; *new_tty_context = new_tty_con; return fd; close_fd: freecon(tty_con); close(fd); return -1; } /** * This function attempts to revert the relabeling done to the tty. * fd - referencing the opened ttyn * ttyn - name of tty to restore * tty_context - original context of the tty * new_tty_context - context tty was relabeled to * * Returns zero on success, non-zero otherwise */ static int restore_tty_label(int fd, const char *ttyn, security_context_t tty_context, security_context_t new_tty_context) { int rc = 0; security_context_t chk_tty_context = NULL; if (!ttyn) goto skip_relabel; if (!new_tty_context) goto skip_relabel; /* Verify that the tty still has the context set by newrole. */ if ((rc = fgetfilecon(fd, &chk_tty_context)) < 0) { fprintf(stderr, "Could not fgetfilecon %s.\n", ttyn); goto skip_relabel; } if ((rc = strcmp(chk_tty_context, new_tty_context))) { fprintf(stderr, _("%s changed labels.\n"), ttyn); goto skip_relabel; } if ((rc = fsetfilecon(fd, tty_context)) < 0) fprintf(stderr, _("Warning! Could not restore context for %s\n"), ttyn); skip_relabel: freecon(chk_tty_context); return rc; } /** * Parses and validates the provided command line options and * constructs a new context based on our old context and the * arguments specified on the command line. On success * new_context will be set to valid values, otherwise its value * is left unchanged. * * Returns zero on success, non-zero otherwise. */ static int parse_command_line_arguments(int argc, char **argv, char *ttyn, security_context_t old_context, security_context_t * new_context, int *preserve_environment) { int flag_index; /* flag index in argv[] */ int clflag; /* holds codes for command line flags */ char *role_s = NULL; /* role spec'd by user in argv[] */ char *type_s = NULL; /* type spec'd by user in argv[] */ char *type_ptr = NULL; /* stores malloc'd data from get_default_type */ char *level_s = NULL; /* level spec'd by user in argv[] */ char *range_ptr = NULL; security_context_t new_con = NULL; security_context_t tty_con = NULL; context_t context = NULL; /* manipulatable form of new_context */ const struct option long_options[] = { {"role", 1, 0, 'r'}, {"type", 1, 0, 't'}, {"level", 1, 0, 'l'}, {"preserve-environment", 0, 0, 'p'}, {"version", 0, 0, 'V'}, {NULL, 0, 0, 0} }; *preserve_environment = 0; while (1) { clflag = getopt_long(argc, argv, "r:t:l:pV", long_options, &flag_index); if (clflag == -1) break; switch (clflag) { case 'V': printf("newrole: %s version %s\n", PACKAGE, VERSION); exit(0); break; case 'p': *preserve_environment = 1; break; case 'r': if (role_s) { fprintf(stderr, _("Error: multiple roles specified\n")); return -1; } role_s = optarg; break; case 't': if (type_s) { fprintf(stderr, _("Error: multiple types specified\n")); return -1; } type_s = optarg; break; case 'l': if (!is_selinux_mls_enabled()) { fprintf(stderr, _("Sorry, -l may be used with " "SELinux MLS support.\n")); return -1; } if (level_s) { fprintf(stderr, _("Error: multiple levels " "specified\n")); return -1; } if (ttyn) { if (fgetfilecon(STDIN_FILENO, &tty_con) >= 0) { if (selinux_check_securetty_context (tty_con) < 0) { fprintf(stderr, _ ("Error: you are not allowed to change levels on a non secure terminal \n")); freecon(tty_con); return -1; } freecon(tty_con); } } level_s = optarg; break; default: fprintf(stderr, "%s\n", USAGE_STRING); return -1; } } /* Verify that the combination of command-line arguments are viable */ if (!(role_s || type_s || level_s)) { fprintf(stderr, "%s\n", USAGE_STRING); return -1; } /* Fill in a default type if one hasn't been specified. */ if (role_s && !type_s) { /* get_default_type() returns malloc'd memory */ if (get_default_type(role_s, &type_ptr)) { fprintf(stderr, _("Couldn't get default type.\n")); send_audit_message(0, old_context, new_con, ttyn); return -1; } type_s = type_ptr; } /* Create a temporary new context structure we extract and modify */ context = context_new(old_context); if (!context) { fprintf(stderr, _("failed to get new context.\n")); goto err_free; } /* Modify the temporary new context */ if (role_s) if (context_role_set(context, role_s)) { fprintf(stderr, _("failed to set new role %s\n"), role_s); goto err_free; } if (type_s) if (context_type_set(context, type_s)) { fprintf(stderr, _("failed to set new type %s\n"), type_s); goto err_free; } if (level_s) { range_ptr = build_new_range(level_s, context_range_get(context)); if (!range_ptr) { fprintf(stderr, _("failed to build new range with level %s\n"), level_s); goto err_free; } if (context_range_set(context, range_ptr)) { fprintf(stderr, _("failed to set new range %s\n"), range_ptr); goto err_free; } } /* Construct the final new context */ if (!(new_con = context_str(context))) { fprintf(stderr, _("failed to convert new context to string\n")); goto err_free; } if (security_check_context(new_con) < 0) { fprintf(stderr, _("%s is not a valid context\n"), new_con); send_audit_message(0, old_context, new_con, ttyn); goto err_free; } *new_context = strdup(new_con); if (!*new_context) { fprintf(stderr, _("Unable to allocate memory for new_context")); goto err_free; } free(type_ptr); free(range_ptr); context_free(context); return 0; err_free: free(type_ptr); free(range_ptr); /* Don't free new_con, context_free(context) handles this */ context_free(context); return -1; } /** * Take care of any signal setup */ static int set_signal_handles(void) { sigset_t empty; /* Empty the signal mask in case someone is blocking a signal */ if (sigemptyset(&empty)) { fprintf(stderr, _("Unable to obtain empty signal set\n")); return -1; } (void)sigprocmask(SIG_SETMASK, &empty, NULL); /* Terminate on SIGHUP. */ if (signal(SIGHUP, SIG_DFL) == SIG_ERR) { fprintf(stderr, _("Unable to set SIGHUP handler\n")); return -1; } return 0; } /************************************************************************ * * All code used for both PAM and shadow passwd goes in this section. * ************************************************************************/ int main(int argc, char *argv[]) { security_context_t new_context = NULL; /* target security context */ security_context_t old_context = NULL; /* original securiy context */ security_context_t tty_context = NULL; /* current context of tty */ security_context_t new_tty_context = NULL; /* new context of tty */ struct passwd pw; /* struct derived from passwd file line */ char *ttyn = NULL; /* tty path */ char **old_environ; int preserve_environment; int fd; pid_t childPid = 0; char *shell_argv0 = NULL; int rc; #ifdef USE_PAM int pam_status; /* pam return code */ pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */ /* This is a jump table of functions for PAM to use when it wants to * * communicate with the user. We'll be using misc_conv(), which is * * provided for us via pam_misc.h. */ struct pam_conv pam_conversation = { misc_conv, NULL }; #endif /* * Step 0: Setup * * Do some intial setup, including dropping capabilities, checking * if it makes sense to continue to run newrole, and setting up * a scrubbed environment. */ if (drop_capabilities(FALSE)) { perror(_("Sorry, newrole failed to drop capabilities\n")); return -1; } if (set_signal_handles()) return -1; #ifdef USE_NLS setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif old_environ = environ; environ = NULL; if (!is_selinux_enabled()) { fprintf(stderr, _("Sorry, newrole may be used only on " "a SELinux kernel.\n")); return -1; } if (security_getenforce() < 0) { fprintf(stderr, _("Could not determine enforcing mode.\n")); return -1; } /* * Step 1: Parse command line and valid arguments * * old_context and ttyn are required for audit logging, * context validation and pam */ if (getprevcon(&old_context)) { fprintf(stderr, _("failed to get old_context.\n")); return -1; } ttyn = ttyname(STDIN_FILENO); if (!ttyn || *ttyn == '\0') { fprintf(stderr, _("Warning! Could not retrieve tty information.\n")); } if (parse_command_line_arguments(argc, argv, ttyn, old_context, &new_context, &preserve_environment)) return -1; /* * Step 2: Authenticate the user. * * Re-authenticate the user running this program. * This is just to help confirm user intent (vs. invocation by * malicious software), not to authorize the operation (which is covered * by policy). Trusted path mechanism would be preferred. */ memset(&pw, 0, sizeof(pw)); if (extract_pw_data(&pw)) goto err_free; #ifdef USE_PAM if (read_pam_config()) { fprintf(stderr, _("error on reading PAM service configuration.\n")); goto err_free; } if (app_service_names != NULL && optind < argc) { if (strcmp(argv[optind], "-c") == 0 && optind < (argc - 1)) { /* * Check for a separate pam service name for the * command when invoked by newrole. */ char *cmd = NULL; rc = sscanf(argv[optind + 1], "%ms", &cmd); if (rc != EOF && cmd) { char *app_service_name = (char *)hashtab_search(app_service_names, cmd); free(cmd); if (app_service_name != NULL) service_name = app_service_name; } } } pam_status = pam_start(service_name, pw.pw_name, &pam_conversation, &pam_handle); if (pam_status != PAM_SUCCESS) { fprintf(stderr, _("failed to initialize PAM\n")); goto err_free; } if (!authenticate_via_pam(ttyn, pam_handle)) #else if (!authenticate_via_shadow_passwd(pw.pw_name)) #endif { fprintf(stderr, _("newrole: incorrect password for %s\n"), pw.pw_name); send_audit_message(0, old_context, new_context, ttyn); goto err_close_pam; } /* * Step 3: Handle relabeling of the tty. * * Once we authenticate the user, we know that we want to proceed with * the action. Prior to this point, no changes are made the to system. */ fd = relabel_tty(ttyn, new_context, &tty_context, &new_tty_context); if (fd < 0) goto err_close_pam; /* * Step 4: Fork * * Fork, allowing parent to clean up after shell has executed. * Child: reopen stdin, stdout, stderr and exec shell * Parnet: wait for child to die and restore tty's context */ childPid = fork(); if (childPid < 0) { /* fork failed, no child to worry about */ int errsv = errno; fprintf(stderr, _("newrole: failure forking: %s"), strerror(errsv)); if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) fprintf(stderr, _("Unable to restore tty label...\n")); if (close(fd)) fprintf(stderr, _("Failed to close tty properly\n")); goto err_close_pam; } else if (childPid) { /* PARENT * It doesn't make senes to exit early on errors at this point, * since we are doing cleanup which needs to be done. * We can exit with a bad rc though */ pid_t pid; int exit_code = 0; int status; do { pid = wait(&status); } while (pid < 0 && errno == EINTR); /* Preserve child exit status, unless there is another error. */ if (WIFEXITED(status)) exit_code = WEXITSTATUS(status); if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) { fprintf(stderr, _("Unable to restore tty label...\n")); exit_code = -1; } freecon(tty_context); freecon(new_tty_context); if (close(fd)) { fprintf(stderr, _("Failed to close tty properly\n")); exit_code = -1; } #ifdef USE_PAM #ifdef NAMESPACE_PRIV pam_status = pam_close_session(pam_handle, 0); if (pam_status != PAM_SUCCESS) { fprintf(stderr, "pam_close_session failed with %s\n", pam_strerror(pam_handle, pam_status)); exit_code = -1; } #endif rc = pam_end(pam_handle, pam_status); if (rc != PAM_SUCCESS) { fprintf(stderr, "pam_end failed with %s\n", pam_strerror(pam_handle, rc)); exit_code = -1; } hashtab_map(app_service_names, free_hashtab_entry, NULL); hashtab_destroy(app_service_names); #endif free(pw.pw_name); free(pw.pw_dir); free(pw.pw_shell); free(shell_argv0); return exit_code; } /* CHILD */ /* Close the tty and reopen descriptors 0 through 2 */ if (ttyn) { if (close(fd) || close(0) || close(1) || close(2)) { fprintf(stderr, _("Could not close descriptors.\n")); goto err_close_pam; } fd = open(ttyn, O_RDWR | O_NONBLOCK); if (fd != 0) goto err_close_pam; rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); if (rc) goto err_close_pam; fd = open(ttyn, O_RDWR | O_NONBLOCK); if (fd != 1) goto err_close_pam; rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); if (rc) goto err_close_pam; fd = open(ttyn, O_RDWR | O_NONBLOCK); if (fd != 2) goto err_close_pam; rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); if (rc) goto err_close_pam; } /* * Step 5: Execute a new shell with the new context in `new_context'. * * Establish context, namesapce and any options for the new shell */ if (optind < 1) optind = 1; /* This is ugly, but use newrole's argv for the exec'd shells argv */ if (asprintf(&shell_argv0, "-%s", pw.pw_shell) < 0) { fprintf(stderr, _("Error allocating shell's argv0.\n")); shell_argv0 = NULL; goto err_close_pam; } argv[optind - 1] = shell_argv0; if (setexeccon(new_context)) { fprintf(stderr, _("Could not set exec context to %s.\n"), new_context); goto err_close_pam; } #ifdef NAMESPACE_PRIV /* Ask PAM to setup session for user running this program */ pam_status = pam_open_session(pam_handle, 0); if (pam_status != PAM_SUCCESS) { fprintf(stderr, "pam_open_session failed with %s\n", pam_strerror(pam_handle, pam_status)); goto err_close_pam; } #endif if (send_audit_message(1, old_context, new_context, ttyn)) { fprintf(stderr, _("Failed to send audit message")); goto err_close_pam_session; } freecon(old_context); old_context=NULL; freecon(new_context); new_context=NULL; #ifdef NAMESPACE_PRIV if (transition_to_caller_uid()) { fprintf(stderr, _("Failed to transition to namespace\n")); goto err_close_pam_session; } #endif if (drop_capabilities(TRUE)) { fprintf(stderr, _("Failed to drop capabilities %m\n")); goto err_close_pam_session; } /* Handle environment changes */ if (restore_environment(preserve_environment, old_environ, &pw)) { fprintf(stderr, _("Unable to restore the environment, " "aborting\n")); goto err_close_pam_session; } execv(pw.pw_shell, argv + optind - 1); /* * Error path cleanup * * If we reach here, then we failed to exec the new shell. */ perror(_("failed to exec shell\n")); err_close_pam_session: #ifdef NAMESPACE_PRIV pam_status = pam_close_session(pam_handle, 0); if (pam_status != PAM_SUCCESS) fprintf(stderr, "pam_close_session failed with %s\n", pam_strerror(pam_handle, pam_status)); #endif err_close_pam: #ifdef USE_PAM rc = pam_end(pam_handle, pam_status); if (rc != PAM_SUCCESS) fprintf(stderr, "pam_end failed with %s\n", pam_strerror(pam_handle, rc)); #endif err_free: freecon(tty_context); freecon(new_tty_context); freecon(old_context); freecon(new_context); free(pw.pw_name); free(pw.pw_dir); free(pw.pw_shell); free(shell_argv0); #ifdef USE_PAM if (app_service_names) { hashtab_map(app_service_names, free_hashtab_entry, NULL); hashtab_destroy(app_service_names); } #endif return -1; } /* main() */ policycoreutils/newrole/newrole.pamd0100644 0000000 0000000 00000000433 13756670066 017047 0ustar000000000 0000000 #%PAM-1.0 # Uncomment the next line if you do not want to enter your passwd everytime # auth sufficient pam_rootok.so auth include system-auth account include system-auth password include system-auth session include system-auth session optional pam_xauth.so policycoreutils/newrole/ru/0040755 0000000 0000000 00000000000 13756670066 015162 5ustar000000000 0000000 policycoreutils/newrole/ru/newrole.10100644 0000000 0000000 00000011537 13756670066 016723 0ustar000000000 0000000 .TH NEWROLE "1" "Октябрь 2000" "Security Enhanced Linux" NSA .SH ИМЯ newrole \- запустить оболочку с новой ролью SELinux .SH ОБЗОР .B newrole [\fB-r\fR|\fB--role\fR] \fIROLE\fR [\fB-t\fR|\fB--type\fR] \fITYPE\fR [\fB-l\fR|\fB--level\fR] [\fB-p\fR|\fB--preserve-environment\fR] \fILEVEL\fR [-- [\fIARGS\fR]...] .SH ОПИСАНИЕ .PP Запустить новую оболочку в новом контексте. Новый контекст берётся из старого контекста, в котором изначально исполнялась .B newrole. Если указан параметр .B -r или .B --role , новый контекст будет иметь роль, заданную \fIROLE\fR. Если указан параметр .B -t или .B --type , новый контекст будет иметь тип (домен), заданный \fITYPE\fR. Если указана роль, но не указан тип, тип по умолчанию берётся из указанной роли. Если указан параметр .B -l или .B --level , новый контекст будет иметь уровень конфиденциальности, заданный \fILEVEL\fR. Если \fILEVEL\fR является диапазоном, новый контекст будет иметь уровень конфиденциальности и допуск, заданные этим диапазоном. Если указан параметр .B -p или .B --preserve-environment , оболочка с новым контекстом SELinux сохранит переменные среды, в ином случае будет создана новая минимальная среда. .PP Дополнительные аргументы .I ARGS могут присутствовать после параметра --, в этом случае они передаются в новую оболочку. В частности, при использовании аргумента \-\- \-c следующий аргумент будет обрабатываться как команда большинством интерпретаторов команд. .PP Если для newrole указан аргумент команды и имя команды найдено в /etc/selinux/newrole_pam.conf, будет использована служба pam, указанная в этом файле для команды, а не обычная конфигурация pam для newrole. Это позволяет устанавливать конфигурацию pam для каждой команды при вызове через newrole, например, чтобы пропустить этап интерактивной повторной аутентификации. .PP Новой оболочкой будет оболочка, указанная в записи пользователя в файле .I /etc/passwd. .PP .B -V или .B --version показывает текущую версию newrole .PP .SH ПРИМЕР .br Смена роли: # id \-Z staff_u:staff_r:staff_t:SystemLow-SystemHigh # newrole \-r sysadm_r # id \-Z staff_u:sysadm_r:sysadm_t:SystemLow-SystemHigh Смена только уровня конфиденциальности: # id \-Z staff_u:sysadm_r:sysadm_t:Unclassified-SystemHigh # newrole \-l Secret # id \-Z staff_u:sysadm_r:sysadm_t:Secret-SystemHigh .PP Смена уровня конфиденциальности и допуска: # id \-Z staff_u:sysadm_r:sysadm_t:Unclassified-SystemHigh # newrole \-l Secret-Secret # id \-Z staff_u:sysadm_r:sysadm_t:Secret .PP Запуск программы с указанной ролью или уровнем: # newrole \-r sysadm_r \-\- \-c "/path/to/app arg1 arg2..." # newrole \-l Secret \-\- \-c "/path/to/app arg1 arg2..." .SH ФАЙЛЫ /etc/passwd - информация об учётных записях пользователей .br /etc/shadow - зашифрованные пароли и информация об устаревании паролей .br /etc/selinux//contexts/default_type - типы по умолчанию для ролей .br /etc/selinux//contexts/securetty_types - типы securetty для изменений уровня .br /etc/selinux/newrole_pam.conf - необязательное сопоставление команд с отдельными службами pam .br .SH СМОТРИТЕ ТАКЖЕ .BR runcon (1) .SH АВТОРЫ .nf Anthony Colatrella Tim Fraser Steve Grubb Darrel Goeddel Michael Thompson Dan Walsh Перевод на русский язык выполнила Герасименко Олеся policycoreutils/po/0040755 0000000 0000000 00000000000 13756670066 013477 5ustar000000000 0000000 policycoreutils/po/Makefile0100644 0000000 0000000 00000007636 13756670066 015150 0ustar000000000 0000000 # # Makefile for the PO files (translation) catalog # PREFIX ?= /usr TOP = ../.. # What is this package? NLSPACKAGE = policycoreutils POTFILE = $(NLSPACKAGE).pot INSTALL = /usr/bin/install -c -p INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DIR = /usr/bin/install -d # destination directory INSTALL_NLS_DIR = $(PREFIX)/share/locale # PO catalog handling MSGMERGE = msgmerge MSGMERGE_FLAGS = -q XGETTEXT = xgettext --default-domain=$(NLSPACKAGE) MSGFMT = msgfmt # All possible linguas PO_LINGUAS := $(sort $(patsubst %.po,%,$(wildcard *.po))) # Only the files matching what the user has set in LINGUAS USER_LINGUAS := $(filter $(patsubst %,%%,$(LINGUAS)),$(PO_LINGUAS)) # if no valid LINGUAS, build all languages USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS)) POFILES = $(patsubst %,%.po,$(USE_LINGUAS)) MOFILES = $(patsubst %.po,%.mo,$(POFILES)) POTFILES = \ ../run_init/open_init_pty.c \ ../run_init/run_init.c \ ../semodule_link/semodule_link.c \ ../audit2allow/audit2allow \ ../semanage/seobject.py \ ../setsebool/setsebool.c \ ../newrole/newrole.c \ ../load_policy/load_policy.c \ ../sestatus/sestatus.c \ ../semodule/semodule.c \ ../setfiles/setfiles.c \ ../semodule_package/semodule_package.c \ ../semodule_deps/semodule_deps.c \ ../semodule_expand/semodule_expand.c \ ../scripts/chcat \ ../scripts/fixfiles \ ../restorecond/stringslist.c \ ../restorecond/restorecond.h \ ../restorecond/utmpwatcher.h \ ../restorecond/stringslist.h \ ../restorecond/restorecond.c \ ../restorecond/utmpwatcher.c \ ../gui/booleansPage.py \ ../gui/fcontextPage.py \ ../gui/loginsPage.py \ ../gui/mappingsPage.py \ ../gui/modulesPage.py \ ../gui/polgen.glade \ ../gui/polgengui.py \ ../gui/portsPage.py \ ../gui/semanagePage.py \ ../gui/statusPage.py \ ../gui/system-config-selinux.glade \ ../gui/system-config-selinux.py \ ../gui/usersPage.py \ ../secon/secon.c \ booleans.py \ ../sepolicy/sepolicy.py \ ../sepolicy/sepolicy/communicate.py \ ../sepolicy/sepolicy/__init__.py \ ../sepolicy/sepolicy/network.py \ ../sepolicy/sepolicy/generate.py \ ../sepolicy/sepolicy/sepolicy.glade \ ../sepolicy/sepolicy/gui.py \ ../sepolicy/sepolicy/manpage.py \ ../sepolicy/sepolicy/transition.py \ ../sepolicy/sepolicy/templates/executable.py \ ../sepolicy/sepolicy/templates/__init__.py \ ../sepolicy/sepolicy/templates/network.py \ ../sepolicy/sepolicy/templates/rw.py \ ../sepolicy/sepolicy/templates/script.py \ ../sepolicy/sepolicy/templates/semodule.py \ ../sepolicy/sepolicy/templates/tmp.py \ ../sepolicy/sepolicy/templates/user.py \ ../sepolicy/sepolicy/templates/var_lib.py \ ../sepolicy/sepolicy/templates/var_log.py \ ../sepolicy/sepolicy/templates/var_run.py \ ../sepolicy/sepolicy/templates/var_spool.py #default:: clean all:: $(MOFILES) booleans.py: sepolicy booleans -a > booleans.py $(POTFILE): $(POTFILES) booleans.py $(XGETTEXT) --keyword=_ --keyword=N_ $(POTFILES) @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ rm -f $(NLSPACKAGE).po; \ else \ mv -f $(NLSPACKAGE).po $(POTFILE); \ fi; \ update-po: Makefile $(POTFILE) refresh-po @rm -f booleans.py refresh-po: Makefile for cat in $(POFILES); do \ lang=`basename $$cat .po`; \ if $(MSGMERGE) $(MSGMERGE_FLAGS) $$lang.po $(POTFILE) > $$lang.pot ; then \ mv -f $$lang.pot $$lang.po ; \ echo "$(MSGMERGE) of $$lang succeeded" ; \ else \ echo "$(MSGMERGE) of $$lang failed" ; \ rm -f $$lang.pot ; \ fi \ done clean: @rm -fv *mo *~ .depend @rm -rf tmp install: $(MOFILES) @for n in $(MOFILES); do \ l=`basename $$n .mo`; \ $(INSTALL_DIR) $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES; \ $(INSTALL_DATA) --verbose $$n $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES/$(NLSPACKAGE).mo; \ done %.mo: %.po $(MSGFMT) -o $@ $< report: @for cat in $(wildcard *.po); do \ echo -n "$$cat: "; \ msgfmt -v --statistics -o /dev/null $$cat; \ done .PHONY: missing depend relabel: policycoreutils/po/af.po0100644 0000000 0000000 00000346253 13756670066 014437 0ustar000000000 0000000 # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: Policycoreutils\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-10-10 16:04-0400\n" "PO-Revision-Date: 2012-03-30 18:14+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Afrikaans (http://www.transifex.com/projects/p/fedora/" "language/af/)\n" "Language: af\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../run_init/run_init.c:67 msgid "" "USAGE: run_init